繁体   English   中英

Google Gson 反序列化问题

[英]Google Gson issue with deserializing

我有一个 Java 类:

public class Object1 {
    private int field1;
    private String field2;
    private Object2 object2;
    private boolean field3;
}

我使用 Gson 将一些 Object1 实例保存为 JSON 字符串:

    String jsonString = new Gson().toJson(object1, Object1.class);

然后我向 Object1 类添加了新的 String 字段:

public class Object1 {
    private int field1;
    private String field2;
    private String field4;
    private Object2 object2;
    private boolean field3;
}

现在我无法使用方法将 json 字符串反序列化为 Object1 实例:

Object1 obj1 = new Gson().fromJson(jsonString, Object1.class);

因为 Gson 抛出异常:

System.err: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 需要一个字符串,但在第 1 行第 444 列路径 $.c 处为 BEGIN_OBJECT,位于 com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read( ReflectiveTypeAdapterFactory.java:224) at com.google.gson.Gson.fromJson(Gson.java:887) at com.google.gson.Gson.fromJson(Gson.java:852) at com.google.gson.Gson.fromJson (Gson.java:801) 在 com.google.gson.Gson.fromJson(Gson.java:773)

但为什么? 我有没有一个字段的 JSON 字符串,这不会成为问题。 为什么我不能反序列化它?

Expected a string but was BEGIN_OBJECT

您的json字符串中的field4不是String类型,请使用Json to POJO生成器来创建适当的对象。

我喜欢使用http://www.jsonschema2pojo.org/

@ user523392说:

成员变量必须与JSON响应中给出的完全匹配

不是这种情况。

有一些选项可用于指定Java字段名称如何映射到JSON元素名称。

在上面原始问题中适用的一种解决方案是用@SerializedName注释Java类成员,以非常明确地声明其映射到的JSON元素名称。

// output: [MyObject: element=value1, elementTwo=value2]

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;

public class Foo
{
  static String jsonInput =
      "{" +
          "\"element\":\"value1\"," +
          "\"@element-two\":\"value2\"" +
      "}";

  public static void main(String[] args)
  {
    GsonBuilder gsonBuilder = new GsonBuilder();
    Gson gson = gsonBuilder.create();
    MyObject object = gson.fromJson(jsonInput, MyObject.class);
    System.out.println(object);
  }
}

class MyObject
{
  String element;

  @SerializedName("@element-two")
  String elementTwo;

  @Override
  public String toString()
  {
    return String.format(
        "[MyObject: element=%s, elementTwo=%s]",
        element, elementTwo);
  }
}

另一种方法是创建自定义FieldNamingStrategy,以指定如何将Java成员名称转换为JSON元素名称。 本示例将相同的名称映射应用于所有Java成员名称。 这种方法不适用于上面的原始示例,因为并非所有JSON元素名称都遵循相同的命名模式-它们并非都以'@'开头,并且有些使用驼峰式命名而不是使用'-来分隔名称部分”。 构建Gson实例(gsonBuilder.setFieldNamingStrategy(new MyFieldNamingStrategy()))时,将使用此FieldNamingStrategy的实例。

class MyFieldNamingStrategy implements FieldNamingStrategy
{
  // Translates the field name into its JSON field name representation.
  @Override
  public String translateName(Field field)
  {
    String name = field.getName();
    StringBuilder translation = new StringBuilder();
    translation.append('@');
    for (int i = 0, length = name.length(); i < length; i++)
    {
      char c = name.charAt(i);
      if (Character.isUpperCase(c))
      {
        translation.append('-');
        c = Character.toLowerCase(c);
      }
      translation.append(c);
    }
    return translation.toString();
  }
}

管理Java字段名称如何映射到JSON元素名称的另一种方法是在构建Gson实例时指定FieldNamingPolicy,例如gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES);。 但是,这也不适用于原始示例,因为它将相同的名称映射策略应用于所有情况。

事实证明,问题在于混淆。

如果您不使用@SerializedName注释结果,JSON可能像这样:

{“ a”:3436213,“ b”:“某些字符串”,“ c”:{.............},“ d”:true}

我们没有使用它,因为它不是DTO。 在这种情况下,我们仅使用JSON来存储一些不重要的内部数据。 但这对我来说是非常有趣的一课。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM