2013-11-27 39 views
1

服務器發送一個JSON。格式不同。 例如:反序列化一個更改內部節點的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如何理解什麼類可以使用?

+0

你寫/您可以更改創建JSON在服務器端代碼? – Scott

+0

不幸的是,這個解決方案無法完成。代碼有效並且不會改變:( –

+0

那麼,因爲你知道每個JSON選項的結構,一個(也許不是最好的)解決方案是在你知道它的結構時就詢問響應,即如果值的地址標記是另一個JSON對象,或者如果數字標記是一個數組。基於結果選擇一個類 – Scott

回答

1

如果您確定在Format1中成員名稱是「phoneNumbers」,而在Format2中它是「phoneNumber」。您可以先玩弄一下JSON字符串,以確定您應該使用哪種類型的格式類。

更公平的做法可能是創建您自己的反序列化器方法並檢查其中的名稱和類型。

+0

與我喜歡的新解串器方法的想法可以是一個例子嗎? –

+0

這個想法是從我的問題之一的答案,檢查它在這裏http://stackoverflow.com/questions/20185625/json-gson-what-is-the-best-way-to-deserialize-to-a -super-class-object-and-then – Robin

+0

良好的聯繫。日Thnx –

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]]