GSON:如何解析可以是列表或字符串的多态性值



我需要解析包含一长串客户列表的JSON文件。在JSON文件中,每个客户可以将一个ID作为字符串:

{
  "cust_id": "87655",
  ...
},

或几个ID作为数组:

   {
      "cust_id": [
        "12345",
        "45678"
      ],
      ...
    },

Customer类如下:

public class Customer {
    @SerializedName("cust_id")
    @Expose
    private String custId;
    public String getCustId() {
        return custId;
    }
    public void setCustId(String custId) {
        this.custId = custId;
    }
}

我使用gson解析JSON:

Gson gson = new Gson()
Customers customers1 = gson.fromJson(json, Customers.class)

尝试解析数组时,它会因com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY而失败。

失败的原因很明显。

我的问题:处理这两种情况的最佳方法是什么(当ID是字符串和当它是字符串数组时(,给定我无法更改JSON文件结构

如果要处理两个方案,则可以使用自定义求职者。当然,您必须将" cust_id"变量更改为列表或数组。

主:

String json1 = "{"cust_id": "87655"}";
String json2 = "{"cust_id": ["12345", "45678"]}";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Customer.class, new CustomerDeserializer());
Gson gson = gsonBuilder.create();
Customer customer1 = gson.fromJson(json1, Customer.class);
System.out.println(customer1);
Customer customer2 = gson.fromJson(json2, Customer.class);
System.out.println(customer2);

客户

public class Customer {
    @SerializedName("cust_id")
    private List<String> custId;
    public List<String> getCustId() {
        return custId;
    }
    public void setCustId(List<String> custId) {
        this.custId = custId;
    }
}

customerDeserializer

public class CustomerDeserializer implements JsonDeserializer<Customer> {
@Override
public Customer deserialize(JsonElement jsonElement, Type typeOf, JsonDeserializationContext context) throws JsonParseException {
    Customer result = null;
    Gson gson = new Gson();
    try {
        // try to deserialize by assuming JSON has a list
        result = gson.fromJson(jsonElement, Customer.class);
    } catch (JsonSyntaxException jse) {
        // error here means JSON has a single string instead of a list
        try {
            // get the single ID
            String custId = jsonElement.getAsJsonObject().get("cust_id").getAsString();
            result = new Customer();
            result.setCustId(Arrays.asList(new String[] {custId}));
        } catch (Exception e) {
            // more error handling here
            e.printStackTrace();
        }
    }
    return result;
}

}

输出

Customer [custId=[87655]]
Customer [custId=[12345, 45678]]

尝试 method overriding

public class Customer {
    @SerializedName("cust_id")
    @Expose
    private String custId;
    public void setCustId(String custId) {
        this.custId = {custId};
    }
    public String[] getCustId() {
        return custId;
    }
    @override
    public void setCustId(String[] custId) {
        this.custId = custId;
    }
}

现在,在代码中,CUSTID的所有值将是数组而不是字符串

您可以简单地将所有值指定为数组,即使只是一个值。

{
  "cust_id": ["87655"],
  ...
},

更新:如果您无法更改JSON,则可以绑定Customer类中的每个字段,除了custId,并手动设置它。

public class Customer {
    private String[] custId;
    public String getCustId() {
        return custId;
    }
    public void setCustId(String custId) {
        custId = new String[] {custId};
    }
    public void setCustId(String[] custId) {
        this.custId = custId;
    }
}

然后手动解析:

Gson gson = new Gson();
Customers customers = gson.fromJson(json, Customers.class);
Object custId = new JSONObject(json).get("cust_id");
if (custId instanceof String) {
  customers.setCustId((String) custId);
else if (custId instanceof JSONArray) {
  customers.setCustId(convertToStringArray(new JSONArray(custId)));
}

参考此。

现在问题是您必须在返回的地图上写下自己的代码才能获得所需的结果。

最新更新