【问题标题】:Gson, how to deserialize array or empty stringGson,如何反序列化数组或空字符串
【发布时间】:2015-07-22 11:44:47
【问题描述】:

我试图将此 json 反序列化为对象数组:

[{
    "name": "item 1",
    "tags": ["tag1"]
},
{
    "name": "item 2",
    "tags": ["tag1","tag2"]
},
{
    "name": "item 3",
    "tags": []
},
{
    "name": "item 4",
    "tags": ""
}]

我的 java 类如下所示:

public class MyObject
{
    @Expose
    private String name;

    @Expose
    private List<String> tags = new ArrayList<String>();
}

问题在于 json 的 tags 属性,它可以是空字符串或数组。现在 gson 给我错误:com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING

我应该如何反序列化这个 json?

我对这个 json 没有任何控制权,它来自 3rd pary api。

【问题讨论】:

    标签: java android json gson


    【解决方案1】:

    我对这个 json 没有任何控制权,它来自 3rd pary api。

    如果您无法控制数据,我认为最好的解决方案是创建自定义反序列化器:

    class MyObjectDeserializer implements JsonDeserializer<MyObject> {
        @Override
        public MyObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            JsonObject jObj = json.getAsJsonObject();
            JsonElement jElement = jObj.get("tags");
            List<String> tags = Collections.emptyList();
            if(jElement.isJsonArray()) {
                tags = context.deserialize(jElement.getAsJsonArray(), new TypeToken<List<String>>(){}.getType());
            }
            //assuming there is an appropriate constructor
            return new MyObject(jObj.getAsJsonPrimitive("name").getAsString(), tags);
        }
    }
    

    它检查"tags" 是否为JsonArray 是做什么的。如果是这种情况,它会像往常一样反序列化它,否则你不要碰它,只需用一个空列表创建你的对象。

    写完之后,您需要在 JSON 解析器中注册它:

    Gson gson = new GsonBuilder().registerTypeAdapter(MyObject.class, new MyObjectDeserializer()).create();
    //here json is a String that contains your input
    List<MyObject> myObjects = gson.fromJson(json, new TypeToken<List<MyObject>>(){}.getType());
    

    运行它,我得到了输出:

    MyObject{name='item 1', tags=[tag1]}
    MyObject{name='item 2', tags=[tag1, tag2]}
    MyObject{name='item 3', tags=[]}
    MyObject{name='item 4', tags=[]}
    

    【讨论】:

      【解决方案2】:

      在将 json 转换为对象之前,将字符串 "tags": "" 替换为 "tags": []

      【讨论】:

      • 就用java.lang.String functionreplaceAll(String regex, String replacement)
      【解决方案3】:

      使用 GSON 的 fromJson() 方法对 JSON 进行反序列化。

      您可以通过下面给出的示例更好地理解这一点:

      import java.util.ArrayList;
      import com.google.gson.Gson;
      import com.google.gson.JsonArray;
      import com.google.gson.JsonElement;
      import com.google.gson.JsonParser;
      
      public class JsonToJava {
      
      /**
       * @param args
       */
      public static void main(String[] args) {
          String json = "[{\"firstName\":\"John\", \"lastName\":\"Doe\", \"id\":[\"10\",\"20\",\"30\"]},"
                  + "{\"firstName\":\"Anna\", \"lastName\":\"Smith\", \"id\":[\"40\",\"50\",\"60\"]},"
                  + "{\"firstName\":\"Peter\", \"lastName\":\"Jones\", \"id\":[\"70\",\"80\",\"90\"]},"
                  + "{\"firstName\":\"Ankur\", \"lastName\":\"Mahajan\", \"id\":[\"100\",\"200\",\"300\"]},"
                  + "{\"firstName\":\"Abhishek\", \"lastName\":\"Mahajan\", \"id\":[\"400\",\"500\",\"600\"]}]";
      
          jsonToJava(json);
      }
      
      private static void jsonToJava(String json) {
          Gson gson = new Gson();
          JsonParser parser = new JsonParser();
          JsonArray jArray = parser.parse(json).getAsJsonArray();
      
          ArrayList<POJO> lcs = new ArrayList<POJO>();
      
          for (JsonElement obj : jArray) {
              POJO cse = gson.fromJson(obj, POJO.class);
              lcs.add(cse);
          }
          for (POJO pojo : lcs) {
              System.out.println(pojo.getFirstName() + ", " + pojo.getLastName()
                      + ", " + pojo.getId());
          }
      }
      

      }

      POJO 类:

      public class POJO {
      
        private String        firstName;
        private String        lastName;
        private String[]  id;
        //Getters and Setters.
      

      希望这能解决您的问题。

      【讨论】:

      • 这是否处理 id:"" 的情况?
      • 你的id应该是数组类型,它会考虑空数组。还有一点,如果您将标签用作数组,那么您的 json 应该是通用的,那么它应该始终遵循相同的规则。如果你给 id : [""],它会起作用。
      【解决方案4】:

      您正在混合数据类型。你不能同时拥有一个数组和一个字符串。改变

      "tags": ""
      

      "tags": null
      

      你可以走了。

      【讨论】:

      • 不幸的是我无法更改 json,它来自 3rd 方 web api。
      • 哦-但是你不能联系他们并指出json无效吗?
      • 我当然可以(而且我会),但他们可能需要时间来修复 api。
      • 您可以添加一个临时修复程序,在将 json 字符串提供给 gson 之前对其进行预处理吗?
      • 是的,也许我只是采用像 Srinivasu Talluri 解释的解决方案。
      【解决方案5】:

      使用 Jacskon 对象映射器

      看下面的简单例子

      [http://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/][1]

      【讨论】:

      • 现在我正在使用 Gson 在我的应用程序中反序列化 json。为了解决这个问题,如果可能的话,我想坚持使用 gson。
      • 用户说他正在使用 gson,所以切换到 jackson 可能不是一个选择。
      • 我不明白为什么当有人询问有关 GSON 的问题时,其他人总是觉得需要提供杰克逊替代方案。
      【解决方案6】:

      Jackson 类型的安全性比 Gson 好得多。有时你会在 Gson 中使用 stackoverflow。

      【讨论】:

      • OP 不会就 Gson vs Jackson 征求意见。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多