GSON解析未指定的类型变量

时间:2013-10-03 16:34:11

标签: java android json parsing gson

我用GSON库解析服务器JSON响应。后端人员有时会告诉我:“由于某些原因,我们无法在JSON中指定变量类型”(旧的PHP,他们不知道如何去做等等)。 GSON喜欢在其对象模型中进行强类型输入。所以我不能将Object解析为String。

GSON等待:

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

但它得到(空数据):

"service": ""

我得到了

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

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

另一个问题: 我如何构建对象,它可以识别不时返回为Integer或String的Integer变量?相同的服务器端问题。

"data": "1"

"data": 1

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

修改 我的解决方案基于Java Developer的答案。
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);
    }

}

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

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

4 个答案:

答案 0 :(得分:1)

在尝试将其反序列化为Response Java对象之前,需要抓取JSON响应。您可以使用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非常聪明,可以执行简单的转换,例如StringInteger等等。因此,反序列化此类JSON属性不会给您带来任何麻烦。

System.out.println(gson.fromJson("10", Integer.class)); // 10
System.out.println(gson.fromJson("\"20\"", Integer.class)); // 20

答案 1 :(得分:0)

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

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

应该用大括号括起来,如下所述:

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

答案 2 :(得分:0)

json结构包含在{}中。您的回答似乎缺失了。您可以在字符串的开头和结尾手动附加{},以使其成为有效的json结构。

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

  

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

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

答案 3 :(得分:0)

如果您想严格遵守gson,可以提供自定义deserializer。由于我们知道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);

我输入了所有这些,如果我错过了一些语法,我道歉。