Gson fromJsonがJsonSyntaxExceptionをスローするのはなぜですか:BEGIN_OBJECTが必要ですが、BEGIN_ARRAYでしたか?

Sotirios Delimanolis:

(この投稿は、以下に提供されるサンプルの回答を含む正規の質問であることを意図しています。)


を使用して、一部のJSONコンテンツをカスタムPOJOタイプに逆シリアル化しようとしていGson#fromJson(String, Class)ます。

このコード

import com.google.gson.Gson;

public class Sample {
    public static void main(String[] args) {
        String json = "{\"nestedPojo\":[{\"name\":null, \"value\":42}]}";
        Gson gson = new Gson();
        gson.fromJson(json, Pojo.class);
    }
}

class Pojo {
    NestedPojo nestedPojo;
}

class NestedPojo {
    String name;
    int value;
}

フォロー例外をスローします

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:200)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:103)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:196)
    at com.google.gson.Gson.fromJson(Gson.java:810)
    at com.google.gson.Gson.fromJson(Gson.java:775)
    at com.google.gson.Gson.fromJson(Gson.java:724)
    at com.google.gson.Gson.fromJson(Gson.java:696)
    at com.example.Sample.main(Sample.java:23)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo
    at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:387)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:189)
    ... 7 more

GsonがJSONテキストをPOJOタイプに適切に変換できないのはなぜですか?

Sotirios Delimanolis:

例外メッセージの状態として

Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 16 path $.nestedPojo

逆シリアル化中に、GsonはJSONオブジェクトを予期していましたが、JSON配列を見つけました。あるものから別のものに変換できなかったため、この例外をスローしました。

ここでは、JSON形式について説明しますつまり、オブジェクト、配列、文​​字列、数値null、およびブール値のtrueとを定義falseます。

Gson(およびほとんどのJSONパーサー)では、次のマッピングが存在します。JSON文字列はJavaにマップされますStringJSON番号はJava Numberタイプにマップされます。JSON配列はCollection型または配列型にマップされます。JSONオブジェクトは、Java Mapタイプ、または通常、カスタムPOJOタイプ(前述していません)にマップされます。nullはJavaにマッピングされnull、ブール値はJava trueおよびにマッピングされますfalse

Gsonは、提供されたJSONコンテンツを反復処理し、要求された対応する型に逆シリアル化しようとします。コンテンツが一致しないか、予期されたタイプに変換できない場合、対応する例外がスローされます。

あなたの場合、あなたは次のJSONを提供しました

{
    "nestedPojo": [
        {
            "name": null,
            "value": 42
        }
    ]
}

ルートでは、nestedPojoこれは、JSON配列であるという名前のメンバーを含むJSONオブジェクトです。そのJSON配列には、単一の要素、2つのメンバーを持つ別のJSONオブジェクトが含まれています。以前に定義されたマッピングを考えると、このJSON nestedPojoはsome Collectionまたはarray型の名前フィールドを持つJavaオブジェクトにマップすることが予想されます。その型はnameおよびという名前の2つのフィールドをvalueそれぞれ定義します。

しかし、あなたはあなたのPojoタイプをフィールドを持つものとして定義しました

NestedPojo nestedPojo;

それは配列型でも型でもありませんCollectionGsonは、このフィールドに対応するJSONをデシリアライズできません。

代わりに、3つのオプションがあります。

  • 予想されるタイプに一致するようにJSONを変更してください

    {
        "nestedPojo": {
            "name": null,
            "value": 42
        }
    }
    
  • PojoCollectionまたは配列型を期待するように型を変更してください

    List<NestedPojo> nestedPojo; // consider changing the name and using @SerializedName
    NestedPojo[] nestedPojo;
    
  • NestedPojo独自の解析ルールを使用して、カスタムデシリアライザを作成して登録します。例えば

    class Custom implements JsonDeserializer<NestedPojo> {
        @Override
        public NestedPojo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            NestedPojo nestedPojo = new NestedPojo();
            JsonArray jsonArray = json.getAsJsonArray();
            if (jsonArray.size() != 1) {
                throw new IllegalStateException("unexpected json");
            }
            JsonObject jsonObject = jsonArray.get(0).getAsJsonObject(); // get only element
            JsonElement jsonElement = jsonObject.get("name");
            if (!jsonElement.isJsonNull()) {
                nestedPojo.name = jsonElement.getAsString();
            }
            nestedPojo.value = jsonObject.get("value").getAsInt();
            return nestedPojo;
        }
    }
    
    Gson gson = new GsonBuilder().registerTypeAdapter(NestedPojo.class, new Custom()).create();
    

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ