Java操作JSON

Java操作JSON

在这之前,我们需要 gson.jar 解析工具包,gson 是 Google解析JSON的一个开源框架,同类的还有 json.lib.jar 等等。

Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。

基本数据类型的解析以及生成

解析

Gson gson = new Gson();
int i = gson.fromJson("100", int.class);              //100
double d = gson.fromJson("\"99.99\"", double.class);  //99.99
boolean b = gson.fromJson("true", boolean.class);     // true
String str = gson.fromJson("String", String.class);   // String

生成

Gson gson = new Gson();
String jsonNumber = gson.toJson(100);       // 100
String jsonBoolean = gson.toJson(false);    // false
String jsonString = gson.toJson("String"); //"String"

POJO类(实体类)的解析以及生成

实体类的解析以及生成我们需要注意实体类中的属性以及JSON对象中的键是否一致,一致则方便转换。

实体类(User.java)

package com.li.entity;

public class User {
    private String name;
    private boolean flag;
    private int age;
    private String address;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public boolean isFlag() {
        return flag;
    }
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public User(String name, boolean flag, int age, String address) {
        super();
        this.name = name;
        this.flag = flag;
        this.age = age;
        this.address = address;
    }

}

测试(操作前需要导入gson JAR包,并导入相应的类)

package com.li;

import com.google.gson.Gson;
import com.li.entity.User;

public class JSONTest {

    public static void main(String[] args) {

        Gson gson = new Gson();

        /*实体类生成JSON:toJson*/
        User user = new User("Li", true, 21, "HuNan");
        String userJSON=gson.toJson(user);
        System.out.println(userJSON);

        /*JSON解析成实体类:fromJson,需要使用反射来了解其内部结构*/
        User user01=gson.fromJson(userJSON, User.class);
        System.out.println(user01.toString());
    }
}

运行结果

{"name":"Li","flag":true,"age":21,"address":"HuNan"}
User [name=Li, flag=true, age=21, address=HuNan]

从上面POJO的生成与解析可以看出 Json 的字段和值的名称和POJO类成员属性名称是一一对应的。但是js在命名时一般采用下划线风格,而Java中一般采用的驼峰法(lowCamelCase),所以有时候可能会出现不和谐的情况。

例如我们稍稍改变一下JSON数据的字段名称:

/*将内部的双引号转义成普通意义*/
String userString="{\"name\":\"Li\",\"flag\":true,\"age\":21,\"add_ress\":\"HuNan\"}";

/*JSON解析成实体类:fromJson,需要使用反射来了解其内部结构*/
User user01=gson.fromJson(userString, User.class);
System.out.println(user01.toString());

输出:

User [name=Li, flag=true, age=21, address=null]

我们知道Gson在序列化和反序列化时需要使用反射,使用反射来查看类的内部结构,说到反射就不得不想到注解,一般各类库都将注解放到annotations包下,打开源码在com.google.gson包下果然有一个annotations,里面有一个SerializedName的注解类,这应该就是我们要找的。

那么对于json中email_address这个属性对应POJO的属性则变成:

@SerializedName("add_ress")
private String address;

这样的话,很好的保留了前端、后台各自的命名习惯。

但是又如果其它地方可以重用该类,其它字段都一样,就 address 字段不一样,又该如何呢?

我们可以为POJO字段提供备选属性名,SerializedName注解提供了两个属性,上面用到了其中一个,别外还有一个属性alternate,接收一个String数组。

@SerializedName(value="add_ress", alternate= {"addre_ss", "ad_dress"})
private String address;

当上面的三个属性(add_ress、addre_ss、ad_dress)都中出现任意一个时均可以得到正确的结果,但是此时如果用address则不行了。。。所以可以这样

@SerializedName(value="address", alternate= {"addre_ss", "ad_dress"})
private String address;

JSON 和 Map的转换

Gson gson = new Gson();

Map<String,String> map = new HashMap<String,String>();   
map.put("key1","value1");   
map.put("key2","value2");   
map.put("key3","value3");   
String json=gson.toJson(map);
System.out.println(json);

Type type = new TypeToken<Map<String, String>>() {}.getType(); 
Map<String, String> map2 = gson.fromJson(json, type);

这个同时也涉及到 gson使用泛型的问题,因为我们在后面指定类型时 Map<String, String> 是行不通的。对于Java来说 Map<String, String>.class 和 Map.class 这俩个的字节码文件只一个那就是 Map.class,这是Java泛型使用时要注意的问题——泛型擦除。

为了解决的上面的问题,Gson为我们提供了TypeToken来实现对泛型的支持,所以应该像这样来指定类型:

Type type = new TypeToken<Map<String, String>>() {}.getType(); 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值