zoukankan      html  css  js  c++  java
  • Gson

     Google 的 Gson 库,Gson 是一个非常强大的库,可以将 JSON 格式的数据转化成 Java 对象,也支持将 Java 对象转成 JSON 数据格式。

    Gson 依赖

    本文将会快速开始使用 Gson 进行序列化操作。由于很多读者都是 Android 开发人员,我们会提供 Java 环境中的 Gson。在开始之前,我们需要引入 Gson 库到自己的项目中,最新的版本是 2.8.0.

    Gradle 项目添加

    compile 'com.google.code.gson:gson:2.8.0'
    

    Maven 项目添加

    <dependencies>
        <dependency>
           <groupId>com.google.code.gson</groupId>
           <artifactId>gson</artifactId>
          <version>2.8.0</version>
           <scope>compile</scope>
        </dependency>
    </dependencies>

    基础
    序列化:
    UserSimple userObject = new UserSimple(
        "Norman",
        "norman@futurestud.io",
        26,
        true
    );
    
    Gson gson = new Gson();
    String userJson = gson.toJson(userObject); 

    反序列化:

    String userJson = "{'age':26,'email':'norman@futurestud.io','isDeveloper':true,'name':'Norman'}";
    Gson gson = new Gson();
    UserSimple userObject = gson.fromJson(userJson, UserSimple.class);

    数组反序列化:

    public class Founder {
        String name;
        int flowerCount;
    }

    String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]"; Gson gson = new Gson(); Founder[] founderArray = gson.fromJson(founderJson, Founder[].class);

     

    列表List反序列化:

    String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]";
    
    Gson gson = new Gson();
    
    Type founderListType = new TypeToken<ArrayList<Founder>>(){}.getType();
    
    List<Founder> founderList = gson.fromJson(founderJson, founderListType);

    列表作为对象的一部分:反序列化时不需要传递 TypeToken

    public class GeneralInfo {
        String name;
        String website;
        List<Founder> founders;
    }
    
    
    String generalInfoJson = "{'name': 'Future Studio Dev Team', 'website': 'https://futurestud.io', 'founders': [{'name': 'Christian', 'flowerCount': 1 }, {'name': 'Marcus','flowerCount': 3 }, {'name': 'Norman','flowerCount': 2 }]}";
    
    Gson gson = new Gson();
    
    GeneralInfo generalInfoObject = gson.fromJson(generalInfoJson, GeneralInfo.class);

    Map反序列化:

    public class AmountWithCurrency {
        String currency;
        int amount;
    }
    
    String dollarJson = "{ '1$': { 'amount': 1, 'currency': 'Dollar'}, '2$': { 'amount': 2, 'currency': 'Dollar'}, '3€': { 'amount': 3, 'currency': 'Euro'} }";
    
    Gson gson = new Gson();
    
    Type amountCurrencyType = new TypeToken<HashMap<String, AmountWithCurrency>>(){}.getType();
    
    HashMap<String, AmountWithCurrency> amountCurrency =
    gson.fromJson(dollarJson, amountCurrencyType);

    Map 数据结构没有根元素,如 "[",我们就可以像解析 List 那用解析嵌套的 Map。

    Set反序列化

    String founderJson = "[{'name': 'Christian','flowerCount': 1}, {'name': 'Marcus', 'flowerCount': 3}, {'name': 'Norman', 'flowerCount': 2}]";
    
    Gson gson = new Gson();
    
    Type founderSetType = new TypeToken<HashSet<Founder>>(){}.getType();
    
    HashSet<Founder> founderSet = gson.fromJson(founderJson, founderSetType);

    泛型序列化:每种数据类型需要 new TypeToken 才能解析成功

    Gson gson = new Gson();
    
    List<Integer> integerList = new ArrayList<>();  
    integerList.add(1);  
    integerList.add(2);  
    integerList.add(3);
    
    List<String> stringList = new ArrayList<>();  
    stringList.add("1");  
    stringList.add("2");  
    stringList.add("3");
    
    Type integerType = new TypeToken<List<Integer>>() {}.getType();  
    Type stringType = new TypeToken<List<String>>() {}.getType();
    
    String integerJson = gson.toJson(integerList, integerType);  
    String stringJson = gson.toJson(stringList, stringType);

    @SerializedName

    @SerializedName 是另一个非常实用的注解。@SerializedName 注解更改了自动匹配 JSON 字段的方式,平时开发中,我们总是默认保持 Java 类属性字段名和 JSON 的字段是一一对应,可有使用并不是总是这样的情况,也许你没有访问继承 Java 类或者你必须遵守公司的命名规则,这就需要使 @SerializedName 注解来匹配 Gson 字段,是一种非常优雅的方式。
    public class UserSimple {     
          @SerializedName("fullName")   
          String name;    
          String email;  
          boolean isDeveloper;  
          int age;
      }
     @SerializedName(value = "fullName", alternate = "username")    
     private String name;  

    SerializedName 接受两个参数,value、alternate。

    SerializedName 改变了默认序列化和默认反序列化的字段取值,序列化时就是 value 的名称就是字段的名称,alternate 属性是用在反序列化上。

    GsonBuider

    public class UserNaming {
       String Name;
       String email_of_developer;
       boolean isDeveloper;
       int _ageOfDeveloper;
    }

    命名规则:

    FieldNamingPolicy.IDENTITY:完全匹配我们 Java model 中的字段名,不管你有没有设置其他注解属性

    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.IDENTITY);
    Gson gson = gsonBuilder.create();
    
    UserNaming user = new UserNaming("Norman", "norman@futurestud.io", true, 26);
    String usersJson = gson.toJson(user);

    输出:

    {
        "Name": "Norman",
        "_ageOfDeveloper": 26,
        "email_of_developer": "norman@futurestud.io",
        "isDeveloper": true
    }

    FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES:将修改生成的 JSON 中的字段名,格式将全部变成小写,并且每个单词用“_” 分割

    {
        "name": "Norman",
        "_age_of_developer": 26,
        "email_of_developer": "norman@futurestud.io",
        "is_developer": true
    }

    FieldNamingPolicy.LOWER_CASE_WITH_DASHES:每个单词用“-” 分隔

    FieldNamingPolicy.UPPER_CAMEL_CASE:规则是每个单词的第一个字母都要大写,其他不变

     {
        "Name": "Norman",
        "_AgeOfDeveloper": 26,
        "Email_of_developer": "norman@futurestud.io",
         "IsDeveloper": true
    }

    FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES:每个单词的第一个字母会大写、每个单词使用空格分隔、含有 “_” 的链接的不会在使用空格

    {
        "Name": "Norman",
        "_Age Of Developer": 26,
        "Email_of_developer": "norman@futurestud.io",
        "Is Developer": true
    }

    FieldNamingStrategy 自定义规则

    FieldNamingStrategy customPolicy = new FieldNamingStrategy() {
        @Override
            public String translateName(Field f) {
                return f.getName().replace("_", "");
          }
    };
    
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.setFieldNamingStrategy(customPolicy);
    Gson gson = gsonBuilder.create();
    
    UserNaming user = new UserNaming("Norman", "norman@futurestud.io", true, 26);
    String usersJson = gson.toJson(user);

    序列化null

    GsonBuilder gsonBuilder = new GsonBuilder();  
    gsonBuilder.serializeNulls(); //重点
    Gson gson = gsonBuilder.create();
    
    UserSimple user = new UserSimple("Norman", null, 26, true);  
    String usersJson = gson.toJson(user);

     输出:

    {
          "age": 26,
          "email": null,
           "isDeveloper": true,
          "name": "Norman"
    }

    忽略策略

     ExclusionStrategies 将 Date 和 boolean 类型的字段忽略、shouldSkipField 是用来忽略单个字段的,如果你想要忽略带有 “_” 的字段

    GsonBuilder gsonBuilder = new GsonBuilder();  
    gsonBuilder.setExclusionStrategies(new ExclusionStrategy() {  
        @Override
        public boolean shouldSkipField(FieldAttributes f) {
            return f.getName().contains("_");
        }
    
        @Override
        public boolean shouldSkipClass(Class<?> incomingClass) {
            return incomingClass == Date.class || incomingClass == boolean.class;
        }
    });
    Gson gson = gsonBuilder.create();
    
    UserDate user = new UserDate("Norman", "norman@futurestud.io", 26, true);  
    String usersJson = gson.toJson(user);

    上面的例子使用的是 setExclusionStrategies 方法,不管是序列化还是反序列化都会起作用,如果我们只想其中一个起作用,选择调下面的方法就行了:

    • addSerializationExclusionStrategy()
    • addDeserializationExclusionStrategy()

    用法和 ExclusionStrategy 的实现一样,可重写两个方法实现。

    基于 Modifiers 的忽略规则:

    public class UserModifier {  
        private String name;
        private transient String email;
        private static boolean isDeveloper;
        private final int age;
    }

    如果你想忽略 final 和 static 类型的字段, 保留 transient 类型的字段

    GsonBuilder gsonBuilder = new GsonBuilder();  
    gsonBuilder.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.FINAL);  
    Gson gson = gsonBuilder.create();
    
    UserModifier user = new UserModifier("Norman", "norman@fs.io", 26, true);  
    String usersJson = gson.toJson(user);

    注解 @Expose

    public class UserSimple {  
            @Expose()
            String name; // equals serialize & deserialize
    
            @Expose(serialize = false, deserialize = false)
            String email; // equals neither serialize nor deserialize
    
            @Expose(serialize = false)
            int age; // equals only deserialize
    
            @Expose(deserialize = false)
            boolean isDeveloper; // equals only serialize
    }

    根据 @Expose 的用法,UserSimple 序列化 JSON 输出只有 name 和 isDeveloper,其他连个字段就不会被输出,因为 serialize 都是 false;

    反序列化的话,只有 email 和 isDeveloper 被忽略,因为 deserialize = false


    transient :使用 transient 来描述字段,将不能被序列化和反序列化
     
    Lenient属性:

    Gson 内部使用的是 JsonReader 类,看源码能发现里面有一个 lenient 的属性,默认是 false,也就是说默认值接受标准的 JSON 格式数据,如果数据有问题,将抛出异常解析失败。

    JsonReader 也提供了设置 lenient 属性的方法,来忽略一些不标准的 JSON 数据格式。


    特殊类型 Floats & Doubles

    如果你 Java 对象中包含一个正常的 Floats 或者 Doubles 类型的数据,是可以正常序列化得到 JSON的,如果你传入 Float.POSITIVE_INFINITY 值,Gson 将会抛出异常,因为这个值是不能符合 JSON 标准的
    解决的办法就是通过 GsonBuilder 设置 serializeSpecialFloatingPointValues() 方法
    GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.serializeSpecialFloatingPointValues();
        Gson gson = gsonBuilder.create();
        UserFloat userFloat = new UserFloat("Norman", Float.POSITIVE_INFINITY);
        String usersJson = gson.toJson(userFloat);
        System.out.println("userJson:" + usersJson);

    自定义序列化:

    public class UserSubscription {  
        String name;
        String email;
        int age;
        boolean isDeveloper;
    
        // new!
        List<Merchant> merchantList;
    }
    
    public class Merchant {  
        private int Id;
        private String name;
    
        // possibly more properties
    }
    JsonSerializer<Merchant> serializer = new JsonSerializer<Merchant>() {  
        @Override
        public JsonElement serialize(Merchant src, Type typeOfSrc, JsonSerializationContext context) {
            JsonObject jsonMerchant = new JsonObject();
    
            jsonMerchant.addProperty("Id", src.getId());
    
            return jsonMerchant;
        }
    };
    
    GsonBuilder gsonBuilder = new GsonBuilder();
    
    
    gsonBuilder.registerTypeAdapter(Merchant.class, serializer);
    
    Gson customGson = gsonBuilder.create();  
    String customJSON = customGson.toJson(subscription);

    自定义序列化List:

    JsonSerializer<List<Merchant>> serializer =  
        new JsonSerializer<List<Merchant>>() {
            @Override
            public JsonElement serialize(List<Merchant> src, Type typeOfSrc, JsonSerializationContext context) {
                JsonObject jsonMerchant = new JsonObject();
    
                List<String> merchantIds = new ArrayList<>(src.size());
                for (Merchant merchant : src) {
                    merchantIds.add("" + merchant.getId());
                }
    
                String merchantIdsAsString = TextUtils.join(",", merchantIds);
    
                jsonMerchant.addProperty("Ids", merchantIdsAsString);
    
                return jsonMerchant;
            }
    }
    
    GsonBuilder gsonBuilder = new GsonBuilder();
    
    Type merchantListType = new TypeToken<List<Merchant>>() {}.getType();  
    
    gsonBuilder.registerTypeAdapter(merchantListType, serializer);
    
    Gson customGson = gsonBuilder.create();  
    String customJSON = customGson.toJson(subscription);
    
    //结果
    {
      "age": 26,
      "email": "norman@fs.io",
      "isDeveloper": true,
      "merchantList": {
        "Ids": "23,42"
      },
      "name": "Norman"
    }

    简化:

    JsonSerializer<List<Merchant>> serializer =  
        new JsonSerializer<List<Merchant>>() {
            @Override
            public JsonElement serialize(List<Merchant> src, Type typeOfSrc, JsonSerializationContext context) {
                JsonArray jsonMerchant = new JsonArray();
    
                for (Merchant merchant : src) {
                    jsonMerchant.add("" + merchant.getId());
                }
    
                return jsonMerchant;
            }
    }
    //结果
    {
      "age": 26,
      "email": "norman@fs.io",
      "isDeveloper": true,
      "merchantList": [
        "23",
        "42"
      ],
      "name": "Norman"
    }
     

    自定义反序列化:

    前三个表示年月日,是一个日期结构,后面四个字段表示一个 model 信息

    //模型
    public class UserDate {  
        private String name;
        private String email;
        private boolean isDeveloper;
        private int age;
        private Date registerDate;
    }
    
    //Json
    "year": 116,
        "month": 5,
        "day": 21,
        "age": 26,
        "email": "norman@futurestud.io",
        "isDeveloper": true,
        "name": "Norman"
    }
    JsonDeserializer<UserDate> deserializer = new JsonDeserializer<UserDate>() {  
        @Override
        public UserDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            JsonObject jsonObject = json.getAsJsonObject();
    
            Date date = new Date(
                    jsonObject.get("year").getAsInt(),
                    jsonObject.get("month").getAsInt(),
                    jsonObject.get("day").getAsInt()
            );
    
            return new UserDate(
                    jsonObject.get("name").getAsString(),
                    jsonObject.get("email").getAsString(),
                    jsonObject.get("isDeveloper").getAsBoolean(),
                    jsonObject.get("age").getAsInt(),
                    date
            );
        }
    };
    
    GsonBuilder gsonBuilder = new GsonBuilder();
    
    
    gsonBuilder.registerTypeAdapter(UserDate.class, deserializer);
    
    Gson customGson = gsonBuilder.create();  
    UserDate customObject = customGson.fromJson(userJson, UserDate.class);

    自定义对象示例创建:

    //Json
    
     {
          "age": 26,
          "email": "norman@fs.io",
          "isDeveloper": true,
          "name": "Norman"
    }
    
    //Model
    public class UserContext {  
        private String name;
        private String email;
        private boolean isDeveloper;
        private int age;
    
        // additional attribute, which is not part of the data model
        private Context context; 
    
        public UserContext(Context context) {
            this.context = context;
        }
    }

    如果你还是用原来的方式来反序列化,那么得到的 Context 肯定是null。你需要在映射之前的构造函数中来创建 Context,这是就需要用到 InstanceCreators。

    String userSimpleJson = ...; // the JSON from the server, see above
    
    GsonBuilder gsonBuilder = new GsonBuilder();  
    gsonBuilder.registerTypeAdapter(  
        UserContext.class, 
        new UserContextInstanceCreator(getApplicationContext())
    );
    Gson customGson = gsonBuilder.create();
    
    UserContext customObject = customGson.fromJson(userSimpleJson, UserContext.class);
    
    private class UserContextInstanceCreator implements InstanceCreator<UserContext> {  
        private Context context;
    
        public UserContextInstanceCreator(Context context) {
            this.context = context;
        }
    
        @Override
        public UserContext createInstance(Type type) {
            // create new object with our additional property
            UserContext userContext = new UserContext(context);
    
            // return it to gson for further usage
            return userContext;
        }
    }

    @JsonAdapter 注解:

    public class MerchantListSerializer implements JsonSerializer<List<Merchant>> {  
        @Override
        public JsonElement serialize(List<Merchant> src, Type typeOfSrc, JsonSerializationContext context) {
            JsonArray jsonMerchant = new JsonArray();
    
            for (Merchant merchant : src) {
                jsonMerchant.add("" + merchant.getId());
            }
    
            return jsonMerchant;
        }
    }
    
    public class UserSubscriptionAnnotation {  
        String name;
        String email;
        int age;
        boolean isDeveloper;
    
        // new!
        @JsonAdapter(MerchantListSerializer.class)
        List<Merchant> merchantList;
    }

    UserSubscriptionAnnotation subscription = new UserSubscriptionAnnotation( "Norman", "norman@fs.io", 26, true, subscribedMerchants);
    Gson gson = new Gson();
    String fullJSON = gson.toJson(subscription);
     

    只有是类的形式,我们才能使用注解 @JsonAdapter 来添加 MerchantListSerializer。就像之前的一些注解用法一样,并添加到你需要序列化的 Java model 中。

    可以看到 merchantList 被添加了 @JsonAdapter(MerchantListSerializer.class) 注解,而 MerchantListSerializer 正是我们序列化过程的实现类,这样我们就不用使用 GsonBuilder 它来创建的 Gson 对象,而是使用默认创建对象就可以,也不需要那些复杂的设置。
     
    反序列化:和序列化不同的是,@JsonAdapter(UserDateDeserializer.class) 注解是要添加在类级别上面,这是一点不同。
     

    转载自:
    作者:無名小子的杂货铺
    链接:https://www.jianshu.com/p/215708d00015
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 相关阅读:
    Spring框架总结(二)
    java.lang.ClassCastException: com.liuyang.annocation.UserAction cannot be cast to com.liuyang.annocation2.UserAction at com.liuyang.annocation2.App.test
    Spring框架总结(一)
    Error creating bean with name 'us' defined in class path resource [com/liuyang/test/DI/beans2.xml]: Cannot resolve reference to bean 'daoa' while setting bean property 'daoa'; nested exception is org.
    互联网系统架构的演进
    重新理解:ASP.NET 异步编程(转)
    Git初级使用教程(转)
    JavaScript开发规范要求
    大型网站架构演化发展历程(转)
    Bootstrap 学习(1)
  • 原文地址:https://www.cnblogs.com/icebutterfly/p/9547792.html
Copyright © 2011-2022 走看看