1

我使用 GSON 库解析服务器 JSON 响应。后端人员有时会告诉我:“由于某种原因,我们无法在 JSON 中指定变量类型”(旧的 php,他们不知道该怎么做等等)。GSON 喜欢在其对象模型中使用强类型。所以我不能将对象解析为字符串。

GSON 等待:

{
    "service":{
        "description":null,
        "name":"Base",
        "id":"4c7a90410529"
    }
}

但它得到(空数据):

"service": ""

我得到

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1396

解析此类响应的最佳做法是什么?

另一个问题:如何构建对象,它可以将不时返回的整数变量识别为整数或字符串?同样的服务器端问题。

"data": "1"

或者

"data": 1

我知道 - 我们应该在 Java 中使用特定类型。但有时做出让步是值得的,
谢谢

编辑: 我的解决方案基于 Java 开发人员的回答。
ServiceDeserializer 类根据其内部值反序列化每个对象。

public class ServiceDeserializer implements JsonDeserializer<ServiceState>{

    @Override
    public ServiceState deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

        String name = "";
        String uuid = "";
        String description = "";

        if (json.isJsonObject()) {
            JsonObject obj = json.getAsJsonObject();

            if (!obj.get("name").isJsonNull()) {
                name = obj.get("name").getAsString();
            }
            if (!obj.get("uuid").isJsonNull()) {
                uuid = obj.get("uuid").getAsString();
            }
            if (!obj.get("description").isJsonNull()) {
                description = obj.get("description").getAsString();
            }
        }
        return new ServiceState(name, uuid, description);
    }

}

还有我的带有 ServiceState 类型适配器的 GSON 构造函数。

Gson gson = new GsonBuilder()
    .registerTypeAdapter(ServiceState.class, new ServiceDeserializer())
    .create();
4

4 回答 4

1

您需要先抓取 JSON 响应,然后再尝试将其反序列化为ResponseJava 对象。您可以使用 Java org.json解析器来验证service对象是否确实存在并以其他方式修复它。

String json = "{\"service\":{\r\n" + 
        "    \"description\":null,\r\n" + 
        "    \"name\":\"Base\",\r\n" + 
        "    \"id\":\"4c7a90410529\"\r\n" + 
        "}}";
String json2 = "{\"service\":\"\"}";

JSONObject root = new JSONObject(json);
// JSONObject root = new JSONObject(json2);
if (root.optJSONObject("service") == null) {
    root.put("service", new JSONObject());
}

Gson gson = new Gson();
Response response = gson.fromJson(root.toString(), Response.class);

System.out.println(response.getService());

输出

// for JSONObject root = new JSONObject(json);
Service [id=4c7a90410529, name=Base, description=null]

// for JSONObject root = new JSONObject(json2);
Service [id=null, name=null, description=null]

其次,Gson它足够聪明,可以进行简单的转换,比如StringtoInteger等。所以,反序列化这样的 JSON 属性不应该给你带来任何麻烦。

System.out.println(gson.fromJson("10", Integer.class)); // 10
System.out.println(gson.fromJson("\"20\"", Integer.class)); // 20
于 2013-10-03T17:41:45.410 回答
0

您的 json 无效,任何 Json 解析器都无法解析语法不正确的 json:

   "service": {
        "description": null,
        "name": "Base",
        "id": "4c7a90410529"
    }

应封装在大括号中,如此处所述:

{
    "service": {
        "description": null,
        "name": "Base",
        "id": "4c7a90410529"
    }
}
于 2013-10-03T16:37:03.660 回答
0

json 结构包含在{}. 您的回复似乎缺少这一点。您可以手动在字符串的开头和结尾附加{and}以使其成为有效的 json 结构。

完成后,您可以使用 Gson 正常解析您的 json 响应。

解析此类响应的最佳做法是什么?

使用足够好的 Json 解析器。这绰绰有余。并尝试让一个类表示与响应完全相同的结构,以避免手动逐级解析 json 响应。

于 2013-10-03T16:37:12.113 回答
0

如果您想严格遵守gson,您可以提供自定义反序列化器。由于我们知道它service要么是基本json字符串的属性,要么是嵌入在其他字符串中的property,我们可以使用反序列化器逐步解析出有问题的组件并相应地处理它们。

 public class MyJsonDeserializer implements JsonDeserializer<YourParsedData> {

   @Override 
   public YourParsedData deserialize(final JsonElement je, final Type type, final JsonDeserialization Context jdc) throws JsonParseException
   {
      final JsonObject obj = je.getAsJsonObject(); //our original full json string
      final JsonElement serviceElement = obj.get("service");


     //here we provide the functionality to handle the naughty element. It seems emtpy string is returned as a JsonPrimitive... so one option
     if(serviceElement instanceOf JsonPrimitive)
     {
       //it was empty do something
     }

     return YourParsedData.create(); //provide the functionality to take in the parsed data
   }
 }

自定义反序列化器将按如下方式调用:

 final Gson gson = new GsonBuilder().registerTypeAdapter(YourParsedData.class, new MyJsonDeserializer()).create();
 gson.fromJson("{service: ''}", YourParsedData.class);

我把所有这些都输入了,所以如果我错过了一些语法,我很抱歉。

于 2013-10-03T19:24:58.577 回答