java json操作

 json操作在开发中虽不是难点,但是常用点,java操作json常用的是gson,jackjson,fastjson等等。jackjson采用单例模式,在解析性能方面,jackjson大概是gson性能的10倍左右,因此,相对更适合大数据处理。 今天我写这篇文章不是来探讨他们的性能,我更倾向于实际开发中的应用,把gson和jackjson在原有基础上进行封装,以使开发更简单。

  gson和jackjson与.NET不同,.net里面json字符串反序列化对象不用严格区分大小写, java对json字符串解析有严格的大小写限制,这是我们开发中必须注意的,gson可在字段设置别名@SerializedName("name")来定义字段大小写,同样jackjson也可设置别名@JsonProperty("name")来定义解析属性大小写,对序列化和反序列化同样生效,好了,开始上代码:

Person类:

public class Person {
	public Person(){};
	public Person(String n,String e,int a,String c){
		this.age=a;
		this.Name=n;
		this.Email=e;
		this.classEs=c;
	}	
	//@JsonProperty("nAme")
	public String Name;
	public String Email;
	//@SerializedName("Age")
	private int age;
	private String classEs;
	//@JsonProperty("nAme")
	public String getName() {
		return Name;
	}
	public void setName(String name) {
		this.Name = name;
	}
	public String getClassEs() {
		return classEs;
	}
	public void setClassEs(String classEs) {
		this.classEs = classEs;
	}
	public String getEmail() {
		return Email;
	}
	public void setEmail(String email) {
		this.Email = email;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}
gson对对象序列化是以属性名称为准,序列化结果与属性名称大小写一致,序列化结果为:{"Name":"sfdgg","Email":"sfdgs3com","age":45,"classEs":"ddfd"}。

jackjson则不同,他以公共属性方法为准,默认为驼峰命名显示,当属性全部为私有属性时,序列化结果为驼峰命名形式的json字符串,但是,当存在公共属性且公共属性不符合驼峰命名法规格的时候,他将会生成一个多余的字段与公共属性一致,如上面的结果为:{"Name":"sfdgg","Email":"sfdgs3com","age":45,"classEs":"ddfd","name":"sfdgg","email":"sfdgs3com"}。同时存在公共属性大小写结果Name和name,Email和email。

因此,gson对设置别名是在属性上面,jackjson中设置别名如果存在公共属性,则需要在公共属性及其对应的get方法上面同时设置别名,才能保持唯一,如果私有属性,只需要在get方法上面进行设置即可,反序列化则是在set方法进行设置。

好了,把封装方法的结果贴出来供大家方便使用,如有不对或需要改正的地方请大家批评指出,我会及时改正。

  /**
     * Gson 对象装json字符串
     * @param 输入需要转化的对象
     * @return 返回转化结果
     */
    public static <T> String ObjToJson(T obj) {
        if (obj == null) {
            return "";
        }
         Gson gson = new Gson();
        String jsonstr = gson.toJson(obj);
        return jsonstr;
    }

    /**
     * jackjson对象转字符串
     * @param 输入的对象
     * @return 转化结果
     */
    public static <T> String MapObjToJson(T obj) {
        if (obj == null) {
            return "";
        }
        ObjectMapper objectMapper = new ObjectMapper();
        String userMapJson = "";
        try {
            userMapJson = objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            return "";
        }
        return userMapJson;
    }

Gson和jackjson对对象 序列化时,对象属性未赋值,Gson默认为序列化结果不显示,jackjson字符串则以属性结果为null进行序列化,反序列化则是gson不存在的结果为空值,jackjson则会报错,这一点要特别注意,可通过配置消除这种错误,默认空值,mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 。好多其他配置大家可以看看。

    /**
     * Gson字符串转对象
     * @param 输入的需要转化的字符串
     * @param 需要转化的对象类型
     * @return 返回转化结果
     * @throws InstantiationException
     * @throws Exception
     */
    public static <T> T JsonToObj(String jsonStr, Class<? extends T> c)
            throws InstantiationException, Exception {
        // Gson gson = new Gson();
        Object obj = gson.fromJson(jsonStr, c);
        T t = c.newInstance();
        if (c.isInstance(obj)) {
            t = (T) obj;
        }
        return t;
    }

    /**
     * jackjson字符串转对象
     * @param 输入的字符串
     * @param 要转化的对象类型
     * @return 转化结果
     * @throws InstantiationException
     * @throws Exception
     */
    public static <T> T MapJsonToObj(String jsonStr, Class<? extends T> c)
            throws InstantiationException, Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        Object obj = objectMapper.readValue(jsonStr, c);
        T t = c.newInstance();
        if (c.isInstance(obj)) {
            t = (T) obj;
        }
        return t;
    }

有的时候我们想直接通过json字符串读取属性的结果,不想转化为对象再来读取value值,则可以通过一下几个方法。

    /**
     * jsckjson根据json字符串取属性结果,第一级目录
     * @param 要搜索的字符串
     * @param 搜索的属性名称(属性名称区分大小写)
     * @return 搜过结果
     */
    public static String getNodevalue(String jsonstr, String indexName) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            JsonNode jnode = objectMapper.readTree(jsonstr);
            return jnode.path(indexName).asText();
        } catch (JsonProcessingException e) {
        } catch (IOException e) {
        }
        return "";
    }

第一级目录则是{"Name":"sfdgg","Email":"sfdgs3com","age":45,"classEs":"ddfd", ,"AAA":{"classEs":"ddfd","BBB","sfggf"}},要搜索属性名称BBB是无法找到的,要找到他必须通过下面方法,其实这两个方法该加上一个判断参数写成一个,既然现在是两个那就按照两个看吧:

    /**
     * 深度遍历搜索属性结果,搜索字符串所有节点
     * @param 要搜过的字符串
     * @param 要搜索的属性名称(属性名称区分大小写)
     * @return 搜索的结果
     */
    public static String getdeepNodevalue(String jsonstr, String indexName) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            JsonNode jnode = objectMapper.readTree(jsonstr);
            return jnode.findValue(indexName).asText();
        } catch (JsonProcessingException e) {
        } catch (IOException e) {
        }
        return "";
    }

上面两个搜索属性名称都是区分大小写的,最后一个是不区分大小写的,全部遍历,一般用这个不太好:

    /**
     * 忽略大小写进行属性搜索
     * @param 要搜索的字符串
     * @param 搜过的属性名称(属性名称不区分大小写)
     * @return 搜索的结果
     */
    public static String getValueIgnoreCase(String jsonstr, String indexName) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String result = "";
            JsonNode jnode = objectMapper.readTree(jsonstr);
            Iterator<String> keys = jnode.getFieldNames();
            while (keys.hasNext()) {
                String fieldName = keys.next();
                if (fieldName.equalsIgnoreCase(indexName)) {
                    result = jnode.path(fieldName).asText();
                    break;
                }
            }
            return result;
        } catch (JsonProcessingException e) {
        } catch (IOException e) {
        }
        return "";
    }

终于写完了,这次发表的java的,下次发表一个.NET的,我的目的就是为了使开发更简单方便。好了,要睡觉了,明天还要上班,有啥不对的还请大家批评指出,不胜感激,谢谢。








  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值