反序列化更改内部节点的JSON

时间:2013-11-27 22:31:09

标签: java android json gson

服务器发送JSON。格式不同。 例如:

{
    "firstName": "X",
    "lastName": "XXX",
    "address": {
        "street": "John Street, 10",
        "postalCode": "12311"
    },
    "phoneNumbers": [
        "812 123-1234",
        "916 123-4567"
    ]
}

但服务器可以发送另一个JSON

{
    "firstName": "X",
    "lastName": "XXX",
    "address": "John Street, 10",
    "postalCode": "101101",
    "phoneNumber": "812123-1234"
}

我的Format1.java

public class Format1 {
    @SerializedName("firstName")
    public String firstName;

    @SerializedName("lastName")
    public String lastName;

    @SerializedName("address")
    public Address address;

    public class Address {
        @SerializedName("street")
        public String street;

        @SerializedName("postalCode")
        public String postalCode;
    }

    @SerializedName("phoneNumbers")
    public String[] phoneNumbers;
}

和Format2.java

public class Format2 {
    @SerializedName("firstName")
    public String firstName;

    @SerializedName("lastName")
    public String lastName;

    @SerializedName("street")
    public String street;

    @SerializedName("postalCode")
    public String postalCode;

    @SerializedName("phoneNumber")
    public String phoneNumber;
}

应用程序不知道从服务器收到什么答案。 Gson如何理解使用哪个类?

2 个答案:

答案 0 :(得分:1)

如果您确定Format1中的成员名称是“phoneNumbers”,而在Format2中则是“phoneNumber”。您可以首先查看JSON字符串以确定应使用哪种类型的格式类。

更公平的方法可能是创建自己的反序列化方法并检查其中的名称和类型。

答案 1 :(得分:1)

你可以做另一个答案中的链接(顺便说一下,可能罗宾的意思是我的回答到他的问题:))这样做:

 JsonParser j = new JsonParser();
 boolean test = j.parse(s1).getAsJsonObject().get("address").isJsonObject()
 if (test) 
   Format1 f1 = gson.fromJson(jsonString, Format1.class);
 else
   Format2 f2 =  gson.fromJson(jsonString, Format2.class);

但由于Format1Format2几乎相同,我建议您只使用一个类(我将其命名为Card)并为此类创建自己的反序列化器。我认为它作为解决方案更优雅,因为你的问题是有两种不同的JSON,而不是你管理的不同类型的对象。这是您可以复制和粘贴并运行的代码。

package stackoverflow.questions;

import java.lang.reflect.Type;
import java.util.*;

import stackoverflow.questions.q19715374.Error;

import com.google.gson.*;
import com.google.gson.reflect.TypeToken;

public class Q20254329 {

   public static class Address {
      private String street;
      private String postalCode;
      @Override
      public String toString() {
         return "Address [street=" + street + ", postalCode=" + postalCode + "]";
      }

   }

   public static class Card {
      private String firstName;
      private String lastName;
      private Address address;
      private List<String> phoneNumbers;
      @Override
      public String toString() {
         return "Card [firstName=" + firstName + ", lastName=" + lastName + ", address=" + address + ", phoneNumbers=" + phoneNumbers + "]";
      }



   }

   public static class CardDeserializer implements JsonDeserializer<Card> {

      public Card deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

          if (json == null)
              return null;
          else {
              Card c = new Card();
              JsonObject jo = json.getAsJsonObject();
              c.firstName = jo.get("firstName").getAsString();
              c.lastName = jo.get("lastName").getAsString();
              JsonElement ja = jo.get("address");

              if (jo.get("address").isJsonObject()){

                 c.address  = context.deserialize(ja, Address.class);
              } else {
                 c.address = new Address();
                 c.address.street = jo.get("address").getAsString();
                 c.address.postalCode = jo.get("postalCode").getAsString();
              }

              JsonElement jsonPhoneNumbers = jo.get("phoneNumbers");
              if (jsonPhoneNumbers != null){
                 Type listType = new TypeToken<List<String>>() {}.getType();
                 c.phoneNumbers = context.deserialize(jsonPhoneNumbers, listType);
              }

              JsonElement jsonPhoneNumber = jo.get("phoneNumber");
              if (jsonPhoneNumber != null){
                 c.phoneNumbers = new ArrayList<>(); //java7 here
                 c.phoneNumbers.add(jsonPhoneNumber.getAsString());
              }
              return c;
          }

      }

  }

   public static void main(String[] args) {
     String s1 = 
     " {                                           "+
     "    \"firstName\": \"X\",                    "+
     "    \"lastName\": \"XXX\",                   "+
     "    \"address\": {                           "+
     "        \"street\": \"John Street, 10\",     "+
     "        \"postalCode\": \"12311\"            "+
     "    },                                       "+
     "    \"phoneNumbers\": [                      "+
     "        \"812 123-1234\",                    "+
     "        \"916 123-4567\"                     "+
     "    ]                                        "+
     "}                                            ";


     String s2 = 
              "{                                      "+
              "    \"firstName\": \"X\",              "+
              "    \"lastName\": \"XXX\",             "+
              "    \"address\": \"John Street, 10\",  "+
              "    \"postalCode\": \"101101\",        "+
              "    \"phoneNumber\": \"812123-1234\"   "+
              "}                                      ";


     GsonBuilder builder = new GsonBuilder();
     builder.registerTypeAdapter(Card.class, new CardDeserializer());

     Gson gson = builder.create();

     Card c1 = gson.fromJson(s1, Card.class);
     System.out.println("First json " + c1);

     Card c2 = gson.fromJson(s2, Card.class);
     System.out.print("Second json " + c2);

   }

}

这是我的结果:

First json Card [firstName=X, lastName=XXX, address=Address [street=John Street, 10, postalCode=12311], phoneNumbers=[812 123-1234, 916 123-4567]]
Second json Card [firstName=X, lastName=XXX, address=Address [street=John Street, 10, postalCode=101101], phoneNumbers=[812123-1234]]