GSON解析未指定类型的变量变量、类型、GSON

2023-09-06 23:03:32 作者:让xx来保护你

我分析与GSON库服务器JSON响应。后端家伙有时告诉我:出于某种原因在JSON我们不能指定变量类型(老PHP的,他们不知道该怎么做等等,等等)。 GSON喜欢在它的对象模型的强类型。所以,我无法分析对象的字符串。

GSON等待:

  {
    服务:{
        说明:空,
        名:基地
        ID:4c7a90410529
    }
}
 

但它得到(空数据):

 服务:
 

和我得到

  java.lang.IllegalStateException:预计BEGIN_OBJECT但串,行1列1396
 
数据类型与变量

什么是最好的做法来分析这样的反应呢?

另一个问题: 如何建立对象,它可以识别的时间,这回时间为整数或字符串整型变量?在同一个服务器端的问题。

 内容:1
 

 内容:1
 

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

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

 公共类ServiceDeserializer实现JsonDeserializer< ServiceState> {

    @覆盖
    公共ServiceState反序列化(JsonElement JSON,类型typeOfT,JsonDeserializationContext上下文)抛出JsonParseException {

        字符串名称=;
        字符串UUID =;
        字符串描述=;

        如果(json.isJsonObject()){
            JSONObject的OBJ = json.getAsJsonObject();

            如果(!obj.get(姓名)。isJsonNull()){
                NAME = obj.get(name)的符getAsString()。
            }
            如果(!obj.get(的uuid)。isJsonNull()){
                UUID = obj.get(的uuid)符getAsString()。
            }
            如果(!obj.get(描述)。isJsonNull()){
                描述= obj.get(说明)符getAsString();
            }
        }
        返回新ServiceState(名称,UUID,说明);
    }

}
 

和我GSON构造型适配器ServiceState。

  GSON GSON =新GsonBuilder()
    .registerTypeAdapter(ServiceState.class,新ServiceDeserializer())
    。创建();
 

解决方案

如果你想坚持严格 GSON 你可以提供一个自定义的解串器。因为我们知道,服务为基 JSON 字符串的属性或嵌入在一些其他的属性,我们可以使用解串器来分步解析出有问题的部件,并相应地处理它们。

 公共类MyJsonDeserializer实现JsonDeserializer< YourParsedData> {

   @覆盖
   公共YourParsedData反序列化(最终JsonElement济,最后一种类型,最终JsonDeserialization上下文JDC)抛出JsonParseException
   {
      最后的JSONObject OBJ = je.getAsJsonObject(); //我们原来的全JSON字符串
      最后JsonElement serviceElement = obj.get(服务);


     //这里我们提供处理顽皮的元素的功能。看来EMPTY的字符串返回一个JsonPrimitive ......这样一个选项
     如果(serviceElement的instanceof JsonPrimitive)
     {
       //里面是空的做一些事情
     }

     返回YourParsedData.create(); //提供的功能,采取在所分析的数据
   }
 }
 

自定义解串器将被称为如下:

 最后GSON GSON =新GsonBuilder()registerTypeAdapter(YourParsedData.class,新MyJsonDeserializer())创建()。
 gson.fromJson({服务:''},YourParsedData.class);
 

我输入这一切了,所以如果我错过了一些语法我的歉意。

I parse server JSON response with GSON library. Backend guys sometimes tell me: "We can't specify variable type in JSON for some reason" (old php, they don't know how to do it and so on and so forth). GSON likes strong typing in its object model. So I can't parse Object as String.

GSON wait for:

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

But it gets (empty data):

"service": ""

And I get

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

What is the best practice to parse such response?

Another question: How can I build object, it can recognize Integer variable which returned from time to time as Integer or as String? The same server side issue.

"data": "1"

or

"data": 1

I know - we should use specific types in Java. But sometime it is worth to make concessions, Thanks

EDIT: My solution based on Java Developer's answer. ServiceDeserializer class deserialize every object depending on its internal value.

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);
    }

}

And my GSON constructor with type adapter for ServiceState.

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

解决方案

If you want to stick with strictly gson you can provide a custom deserializer. Since we know that service is either a property of the base json string or embedded within some other property, we can use the deserializer to step-wise parse out the offending components and handle them accordingly.

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

The custom deserializer would be called as follows:

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

I typed all this up so if I missed some syntax my apologies.