簡體   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