Gson解析による複数のJsonObjectを含む複雑なjson
12181 ワード
本明細書に対応する項目はMultiTypeJsonParserであり、項目アドレスhttps://github.com/sososeen09/MultiTypeJsonParser
0前奏
0前奏
Gsonを使用してjsonを解析するのはよくあるはずですが、ほとんどの場合、Gsonオブジェクトを作成し、jsonと対応するJavaクラスに基づいて解析すればいいのです.Gson gson = new Gson();
Person person = gson.form(json,Person.class);
しかし、比較的複雑なjsonについては、例えば以下のようにattributes対応のjsonObjectのフィールドが全く異なるので、このときはもっと簡単に上記の方法では解析できません.{
"total": 2,
"list": [
{
"type": "address",
"attributes": {
"street": "NanJing Road",
"city": "ShangHai",
"country": "China"
}
},
{
"type": "name",
"attributes": {
"first-name": "Su",
"last-name": "Tu"
}
}
]
}
もちろん、私たちは一歩一歩で解決できないと言っていますが、少し愚かな方法でもいいです.たとえばattributesに対応するjsonObjectを手動で解析し,その同級typeに対応するvalueからこのjsonObjectに対応するJavaクラスがどれであるかを判断し,最後にgson.from()
手法を用いてattributesに対応するJavaオブジェクトを解析する.
ListInfoWithType listInfoWithType = new ListInfoWithType();
// org.json JSONObject
JSONObject jsonObject = new JSONObject(TestJson.TEST_JSON_1);
int total = jsonObject.getInt("total");
// org.json JSONArray
JSONArray jsonArray = jsonObject.getJSONArray("list");
Gson gson = new Gson();
List list = new ArrayList<>();
//
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject innerJsonObject = jsonArray.getJSONObject(i);
Class extends Attribute> clazz;
String type = innerJsonObject.getString("type");
if (TextUtils.equals(type, "address")) {
clazz = AddressAttribute.class;
} else if (TextUtils.equals(type, "name")) {
clazz = NameAttribute.class;
} else {
//
continue;
}
AttributeWithType attributeWithType = new AttributeWithType();
// Gson
Attribute attribute = gson.fromJson(innerJsonObject.getString("attributes"), clazz);
attributeWithType.setType(type);
attributeWithType.setAttributes(attribute);
list.add(attributeWithType);
}
listInfoWithType.setTotal(total);
listInfoWithType.setList(list);
これによりjson全体の逆シーケンス化が実現するが、この方式は面倒で少しも優雅ではなく、プロジェクトにこのような状況が多く存在すれば、多くの体力労働を繰り返すことになる.どのようにもっと優雅で、もっと汎用的にこのような問題を解決するかは、ネット上で答えが見つからず、Gsonを深く研究するしかなかった.そんな目的でGsonのドキュメントをめくってみると、一言
Gson can work with arbitrary Java objects including pre-existing objects that you do not have source code of.
Gsonは任意のJavaオブジェクトを処理することができます.では、上記のような逆シーケンス化の場合、Gsonもできるはずです.Gsonの文書を検討することにより,JsonDeserializerをカスタマイズすることにより,このようなjsonObjectタイプの異なる解析を実現できることが分かった.
ほとんどの場合,Gsonは直接newで作成されることが知られているが,GsonBuilderというクラスを用いてGsonを生成することもできる. Gson gson = new GsonBuilder()
.registerTypeAdapter(Id.class, new IdTypeAdapter())
.enableComplexMapKeySerialization()
.serializeNulls()
.setDateFormat(DateFormat.LONG)
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.setPrettyPrinting()
.setVersion(1.0)
.create();
GsonBuilderはregisterTypeAdapter()メソッドでターゲットクラスを登録します.ターゲットクラスをシーケンス化または逆シーケンス化すると、登録したtypeAdapterが呼び出され、Gsonのシーケンス化および逆シーケンス化プロセスに手動で介入することができます.
GsonBuilderのregisterTypeAdapte()メソッドの2番目のパラメータはObjectタイプです.つまり、JsonSerializer、JsonDeserializer、InstanceCreator、TypeAdapterの複数のタイプを登録できることを意味します.現在サポートされているタイプはJsonSerializerです. public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter)
ドラムを叩いて、ツールクラスを書きました.上の複雑なjsonに対して、10行未満のコードでできて、優雅で汎用的です.MultiTypeJsonParser multiTypeJsonParser = new MultiTypeJsonParser.Builder()
.registerTypeElementName("type")
.registerTargetClass(Attribute.class)
.registerTargetUpperLevelClass(AttributeWithType.class)
.registerTypeElementValueWithClassType("address", AddressAttribute.class)
.registerTypeElementValueWithClassType("name", NameAttribute.class)
.build();
ListInfoWithType listInfoWithType = multiTypeJsonParser.fromJson(TestJson.TEST_JSON_1, ListInfoWithType.class);
本稿では、JsonDeserializerをカスタマイズすることによって、複雑なタイプのjsonを解析するための一般的なツールクラスを実現する方法を簡単に分析します.後で類似の問題に遭遇する場合、この処理方法は問題を解決する構想を提供することができる.特定のコードとインスタンスは、プロジェクトを表示できます.アイデアにヒントがあれば、コミュニケーションとスターを歓迎します.
1 JsonDeserializer紹介
JsonDeserializerはインタフェースで、使用するときにこのインタフェースを実現し、GsonBuilderで具体的なタイプを登録する必要があります.対応するクラスに逆シーケンス化すると、このカスタムJsonDeserialize()メソッドが呼び出されます.Gson解析の過程をよりよく理解するために,この方法のいくつかのパラメータについて説明する.public interface JsonDeserializer {
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException;
}
1.1 JsonElement
JsonElementはGsonの要素を表します.これは抽象クラスで、JsonObject、JsonArray、JsonPrimitive、JsonNullの4つのサブクラスがあります.1.JsonObjectはname-value型を含むjson文字列を表し、nameは文字列であり、valueは他のタイプのJsonElement要素であってもよい.jsonで「{}」で包まれた全体がJsonObjectです.たとえば// "attributes" name, {} value, value JsonObject
"attributes": {
"first-name": "Su",
"last-name": "Tu"
}
2.JsonArrayクラスはGsonで配列タイプを表し、1つの配列はJsonElementの集合であり、この集合の各タイプは異なる可能性がある.これは秩序化された集合であり,要素の追加順序が維持されていることを意味する.上記の例ではlist対応の「[]」に包まれたjsonがJsonArrayです.
3.**JsonPrimitive**これは、Javaの8つの基本タイプと対応するパッケージタイプ、Stringタイプを含むjsonの元のタイプと考えられる値です.例えば、上の「first-name」に対応する「Su」はStringタイプのJsonPrimitiveです.
4.JsonNull名前でも推測できますが、これはnull値を表しています.
1.2 Type
TypeはJavaのすべてのタイプの最上位インタフェースであり、そのサブクラスはGenericArrayType、ParameterizedType、Type Variable、WildcardTypeであり、これはjavaである.lang.reflectパッケージの下のクラス.また,我々が最もよく知っているクラスClassもTypeインタフェースを実現している.
一般的にGsonBuilderのregisterType Adapter()を呼び出して登録し、最初のパラメータはClassタイプを使用すればよい.
1.3 JsonDeserializationContext
このクラスは、逆シーケンス中に他のクラスからカスタムJsonDeserialize()メソッドを呼び出すと渡され、Gsonで唯一の実装はTreeType Adapterのプライベートな内部クラスGsonContextImplです.オブジェクトを取得するには、カスタムJsonDeserialize()でJsonDeserializationContextのdeserialize()メソッドを呼び出します.
ただし、JsonDeserializationContextに渡されたjsonがJsonDeserializerのjsonと同じであれば、デッドループ呼び出しを招く可能性があることを覚えておいてください.
2考え方分析
2.1 JavaBeanの作成
やはり一番上のjsonで分析して、listでJsonArrayに対応して、その中の2つのJsonObjectの中で、attributesで対応するJsonObjectフィールドは全く違いますが、統一のためにJavaBeanを書くときに共通の親を設定することができます.それは空ですが.public class Attribute {
...
}
public class AddressAttribute extends Attribute {
private String street;
private String city;
private String country;
... get/set
}
public class NameAttribute extends Attribute {
@SerializedName("first-name")
private String firstname;
@SerializedName("last-name")
private String lastname;
... get/set
}
AttributeというSuperClassを設定するのはGsonBuilderで登録するためだけで、具体的に解析するときはtypeの対応するタイプに応じて対応するClassを見つけます. gsonBuilder.registerTypeAdapter(Attribute.class, new AttributeJsonDeserializer());
ここまで来るとtype対応のvalueはきっと具体的なJavaBeanに対応しているに違いないと思います.例えばここで"address"——AddressAttribute.class
"name"——NameAttribute.class
typeが「address」なら、gsonでAddressAttributeを取ることができます.classと対応するjsonは解析する.Attribute attribute = gson.form(addressJson,AddressAttribute.class);
2.2 jsonを対応するJavaBeanに正確に変換する方法
親クラスAttributeを登録し、逆シーケンス化でAttributeを解析する必要がある場合、対応するjsonをパラメータとしてカスタムJsonDeserializerにコールバックします.私たちは次の方法で自分の論理を書いて、私たちが必要とするAttributeオブジェクトを得ることができます. public Attribute deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
でも細心の注意を払った友達は気づくはずですが、この時伝えたjsonはそうかもしれません.{
"street": "NanJing Road",
"city": "ShangHai",
"country": "China"
}
そうかもしれない{
"first-name": "Su",
"last-name": "Tu"
}
AddressAttributeに解析するかNameAttributeに解析するかをどのように知っていますか??
具体的にどのように解析するかを考えてみましょう.typeが対応するvalueを知る必要があります.このtypeはattributesと同級のフィールドで、さっきのようにこのvalueを手に入れることを望んでいないに違いない.
もう一度考えてみましょう.このtypeに対応するvalueが何なのかを知ることができるのはattributesの前のレベルのjsonに違いありません.{
"type": "name",
"attributes": {
...
}
}
では、GsonBuilderにtypeAdapterを登録して、この外層のjsonを解析してもいいですか?もちろんいいです. gsonBuilder.registerTypeAdapter(AttributeWithType.class, new AttributeWithTypeJsonDeserializer());
このAttributeWithTypeは外層のjson対応JavaBeanですpublic class AttributeWithType {
private String type;
private Attribute attributes;
...
}
AttributeWithTypeというクラスを逆シーケンス化すると、このtypeに対応するvalueを取得し、このvalueを奥層のAttributeに対応するJsonDeserializerに渡すことができます.これにより、valueが「address」または「name」であることに基づいて、AddresAttributeまたはNameAttributeを逆シーケンス化することができます.
2.3穴がある
前述したように、JsonDeserializationContextを呼び出す方法はデッドサイクルに注意しなければならない.具体的な実践では、JsonDeserializationContextを呼び出す方法はありませんが、デッドサイクルが発生しています.私がこのように使っているからです. AttributeWithType attributeWithType = gson.fromJson(json, AttributeWithType.class);
一見問題ないですね.問題はこのgsonにあります.このgsonは解析AttributeWithTypeに登録されているGsonBuilderによって作成された.gson.fromJson()メソッドのjsonはAttributeWithTypeに対応する逆シーケンス化json,gsonである.fromJson()の内部では、AttributeWithType対応のJsonDeserialize()メソッドが再び呼び出され、デッドサイクルが発生します.
デッドサイクルを避ける方法は、GsonBuilderでgsonを新規作成することです.このGsonBuilderはAttributeWithTypeを登録せず、Attributeだけを登録して解析します.
3より一般的な
1.プロジェクトには、外部に個別のtype要素がなく、他の要素と同じJsonObjectに配置された別のフォーマットのjsonも存在する可能性があります.このようなフォーマットは、外層のtypeAdaperを登録する必要がなく、より手間が省けます.{
"total": 2,
"list": [
{
"type": "address",
"street": "NanJing Road",
"city": "ShangHai",
"country": "China"
},
{
"type": "name",
"first-name": "Su",
"last-name": "Tu"
}
]
}
MultiTypeJsonParser multiTypeJsonParser = new MultiTypeJsonParser.Builder()
.registerTypeElementName("type")
.registerTargetClass(Attribute.class)
// jsonObejct , Type,
// .registerTargetUpperLevelClass(AttributeWithType.class)
.registerTypeElementValueWithClassType("address", AddressAttribute.class)
.registerTypeElementValueWithClassType("name", NameAttribute.class)
.build();
ListInfoWithType listInfoWithType = multiTypeJsonParser.fromJson(TestJson.TEST_JSON_1, ListInfoWithType.class);
2.解析中にMultiTypeJsonParserのBuilderに登録されていないタイプがある場合、解析中に対応するjsonObjectに遭遇するとnullに戻ります.例えば以下のようなjsonでは,「type」に対応する「parents」が登録されていなければ,逆シーケンス化の際にこのjsonが表すオブジェクトはnullである. {
"type": "parents",
"attributes": {
"mather": "mi lan",
"father": "lin ken"
}
}
Androidでは逆シーケンスのようなjsonの後、一般的に得られるオブジェクトの設定をリストコントロールに設定し、バックエンドで返されるjsonに以前に登録されていなかったタイプが含まれている場合、プログラムがcrashに至らないように逆シーケンス化されたnullオブジェクトをフィルタリングする必要があり、プロジェクトにはツールクラスListItemFilterがセット内のnullの要素をフィルタリングできるように提供されている.
4結語
このようなタイプの異なるJsonObjectをどのように優雅に解析するかについては、最初は考えが欠けていたが、ネット上で適切なドキュメントを調べられなかった.しかし、Gsonのドキュメントとソースコードを表示することで、自分の理解と分析を通じて、この過程を徐々に完成しました.私の1つの感触は、公式のドキュメントを多く見て、盲目的にソリューションを検索するよりも良いはずです.
コードは最高のドキュメントで、本文は簡単にいくつかの実現構想を紹介しただけで、文の中で貼ったいくつかのコードは説明の便利さのためで、プロジェクトの中のコードといくつかの違いがあるかもしれません.具体的な使用はプロジェクトの例を見ることができます.
もし問題があれば、issueや伝言を歓迎します.もしあなたに役に立つなら、スターを歓迎します.
リファレンス
Gson公式ドキュメント
Gson gson = new Gson();
Person person = gson.form(json,Person.class);
{
"total": 2,
"list": [
{
"type": "address",
"attributes": {
"street": "NanJing Road",
"city": "ShangHai",
"country": "China"
}
},
{
"type": "name",
"attributes": {
"first-name": "Su",
"last-name": "Tu"
}
}
]
}
ListInfoWithType listInfoWithType = new ListInfoWithType();
// org.json JSONObject
JSONObject jsonObject = new JSONObject(TestJson.TEST_JSON_1);
int total = jsonObject.getInt("total");
// org.json JSONArray
JSONArray jsonArray = jsonObject.getJSONArray("list");
Gson gson = new Gson();
List list = new ArrayList<>();
//
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject innerJsonObject = jsonArray.getJSONObject(i);
Class extends Attribute> clazz;
String type = innerJsonObject.getString("type");
if (TextUtils.equals(type, "address")) {
clazz = AddressAttribute.class;
} else if (TextUtils.equals(type, "name")) {
clazz = NameAttribute.class;
} else {
//
continue;
}
AttributeWithType attributeWithType = new AttributeWithType();
// Gson
Attribute attribute = gson.fromJson(innerJsonObject.getString("attributes"), clazz);
attributeWithType.setType(type);
attributeWithType.setAttributes(attribute);
list.add(attributeWithType);
}
listInfoWithType.setTotal(total);
listInfoWithType.setList(list);
Gson gson = new GsonBuilder()
.registerTypeAdapter(Id.class, new IdTypeAdapter())
.enableComplexMapKeySerialization()
.serializeNulls()
.setDateFormat(DateFormat.LONG)
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.setPrettyPrinting()
.setVersion(1.0)
.create();
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter)
MultiTypeJsonParser multiTypeJsonParser = new MultiTypeJsonParser.Builder()
.registerTypeElementName("type")
.registerTargetClass(Attribute.class)
.registerTargetUpperLevelClass(AttributeWithType.class)
.registerTypeElementValueWithClassType("address", AddressAttribute.class)
.registerTypeElementValueWithClassType("name", NameAttribute.class)
.build();
ListInfoWithType listInfoWithType = multiTypeJsonParser.fromJson(TestJson.TEST_JSON_1, ListInfoWithType.class);
JsonDeserializerはインタフェースで、使用するときにこのインタフェースを実現し、GsonBuilderで具体的なタイプを登録する必要があります.対応するクラスに逆シーケンス化すると、このカスタムJsonDeserialize()メソッドが呼び出されます.Gson解析の過程をよりよく理解するために,この方法のいくつかのパラメータについて説明する.
public interface JsonDeserializer {
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException;
}
1.1 JsonElement
JsonElementはGsonの要素を表します.これは抽象クラスで、JsonObject、JsonArray、JsonPrimitive、JsonNullの4つのサブクラスがあります.1.JsonObjectはname-value型を含むjson文字列を表し、nameは文字列であり、valueは他のタイプのJsonElement要素であってもよい.jsonで「{}」で包まれた全体がJsonObjectです.たとえば
// "attributes" name, {} value, value JsonObject
"attributes": {
"first-name": "Su",
"last-name": "Tu"
}
2.JsonArrayクラスはGsonで配列タイプを表し、1つの配列はJsonElementの集合であり、この集合の各タイプは異なる可能性がある.これは秩序化された集合であり,要素の追加順序が維持されていることを意味する.上記の例ではlist対応の「[]」に包まれたjsonがJsonArrayです.
3.**JsonPrimitive**これは、Javaの8つの基本タイプと対応するパッケージタイプ、Stringタイプを含むjsonの元のタイプと考えられる値です.例えば、上の「first-name」に対応する「Su」はStringタイプのJsonPrimitiveです.
4.JsonNull名前でも推測できますが、これはnull値を表しています.
1.2 Type
TypeはJavaのすべてのタイプの最上位インタフェースであり、そのサブクラスはGenericArrayType、ParameterizedType、Type Variable、WildcardTypeであり、これはjavaである.lang.reflectパッケージの下のクラス.また,我々が最もよく知っているクラスClassもTypeインタフェースを実現している.
一般的にGsonBuilderのregisterType Adapter()を呼び出して登録し、最初のパラメータはClassタイプを使用すればよい.
1.3 JsonDeserializationContext
このクラスは、逆シーケンス中に他のクラスからカスタムJsonDeserialize()メソッドを呼び出すと渡され、Gsonで唯一の実装はTreeType Adapterのプライベートな内部クラスGsonContextImplです.オブジェクトを取得するには、カスタムJsonDeserialize()でJsonDeserializationContextのdeserialize()メソッドを呼び出します.
ただし、JsonDeserializationContextに渡されたjsonがJsonDeserializerのjsonと同じであれば、デッドループ呼び出しを招く可能性があることを覚えておいてください.
2考え方分析
2.1 JavaBeanの作成
やはり一番上のjsonで分析して、listでJsonArrayに対応して、その中の2つのJsonObjectの中で、attributesで対応するJsonObjectフィールドは全く違いますが、統一のためにJavaBeanを書くときに共通の親を設定することができます.それは空ですが.public class Attribute {
...
}
public class AddressAttribute extends Attribute {
private String street;
private String city;
private String country;
... get/set
}
public class NameAttribute extends Attribute {
@SerializedName("first-name")
private String firstname;
@SerializedName("last-name")
private String lastname;
... get/set
}
AttributeというSuperClassを設定するのはGsonBuilderで登録するためだけで、具体的に解析するときはtypeの対応するタイプに応じて対応するClassを見つけます. gsonBuilder.registerTypeAdapter(Attribute.class, new AttributeJsonDeserializer());
ここまで来るとtype対応のvalueはきっと具体的なJavaBeanに対応しているに違いないと思います.例えばここで"address"——AddressAttribute.class
"name"——NameAttribute.class
typeが「address」なら、gsonでAddressAttributeを取ることができます.classと対応するjsonは解析する.Attribute attribute = gson.form(addressJson,AddressAttribute.class);
2.2 jsonを対応するJavaBeanに正確に変換する方法
親クラスAttributeを登録し、逆シーケンス化でAttributeを解析する必要がある場合、対応するjsonをパラメータとしてカスタムJsonDeserializerにコールバックします.私たちは次の方法で自分の論理を書いて、私たちが必要とするAttributeオブジェクトを得ることができます. public Attribute deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
でも細心の注意を払った友達は気づくはずですが、この時伝えたjsonはそうかもしれません.{
"street": "NanJing Road",
"city": "ShangHai",
"country": "China"
}
そうかもしれない{
"first-name": "Su",
"last-name": "Tu"
}
AddressAttributeに解析するかNameAttributeに解析するかをどのように知っていますか??
具体的にどのように解析するかを考えてみましょう.typeが対応するvalueを知る必要があります.このtypeはattributesと同級のフィールドで、さっきのようにこのvalueを手に入れることを望んでいないに違いない.
もう一度考えてみましょう.このtypeに対応するvalueが何なのかを知ることができるのはattributesの前のレベルのjsonに違いありません.{
"type": "name",
"attributes": {
...
}
}
では、GsonBuilderにtypeAdapterを登録して、この外層のjsonを解析してもいいですか?もちろんいいです. gsonBuilder.registerTypeAdapter(AttributeWithType.class, new AttributeWithTypeJsonDeserializer());
このAttributeWithTypeは外層のjson対応JavaBeanですpublic class AttributeWithType {
private String type;
private Attribute attributes;
...
}
AttributeWithTypeというクラスを逆シーケンス化すると、このtypeに対応するvalueを取得し、このvalueを奥層のAttributeに対応するJsonDeserializerに渡すことができます.これにより、valueが「address」または「name」であることに基づいて、AddresAttributeまたはNameAttributeを逆シーケンス化することができます.
2.3穴がある
前述したように、JsonDeserializationContextを呼び出す方法はデッドサイクルに注意しなければならない.具体的な実践では、JsonDeserializationContextを呼び出す方法はありませんが、デッドサイクルが発生しています.私がこのように使っているからです. AttributeWithType attributeWithType = gson.fromJson(json, AttributeWithType.class);
一見問題ないですね.問題はこのgsonにあります.このgsonは解析AttributeWithTypeに登録されているGsonBuilderによって作成された.gson.fromJson()メソッドのjsonはAttributeWithTypeに対応する逆シーケンス化json,gsonである.fromJson()の内部では、AttributeWithType対応のJsonDeserialize()メソッドが再び呼び出され、デッドサイクルが発生します.
デッドサイクルを避ける方法は、GsonBuilderでgsonを新規作成することです.このGsonBuilderはAttributeWithTypeを登録せず、Attributeだけを登録して解析します.
3より一般的な
1.プロジェクトには、外部に個別のtype要素がなく、他の要素と同じJsonObjectに配置された別のフォーマットのjsonも存在する可能性があります.このようなフォーマットは、外層のtypeAdaperを登録する必要がなく、より手間が省けます.{
"total": 2,
"list": [
{
"type": "address",
"street": "NanJing Road",
"city": "ShangHai",
"country": "China"
},
{
"type": "name",
"first-name": "Su",
"last-name": "Tu"
}
]
}
MultiTypeJsonParser multiTypeJsonParser = new MultiTypeJsonParser.Builder()
.registerTypeElementName("type")
.registerTargetClass(Attribute.class)
// jsonObejct , Type,
// .registerTargetUpperLevelClass(AttributeWithType.class)
.registerTypeElementValueWithClassType("address", AddressAttribute.class)
.registerTypeElementValueWithClassType("name", NameAttribute.class)
.build();
ListInfoWithType listInfoWithType = multiTypeJsonParser.fromJson(TestJson.TEST_JSON_1, ListInfoWithType.class);
2.解析中にMultiTypeJsonParserのBuilderに登録されていないタイプがある場合、解析中に対応するjsonObjectに遭遇するとnullに戻ります.例えば以下のようなjsonでは,「type」に対応する「parents」が登録されていなければ,逆シーケンス化の際にこのjsonが表すオブジェクトはnullである. {
"type": "parents",
"attributes": {
"mather": "mi lan",
"father": "lin ken"
}
}
Androidでは逆シーケンスのようなjsonの後、一般的に得られるオブジェクトの設定をリストコントロールに設定し、バックエンドで返されるjsonに以前に登録されていなかったタイプが含まれている場合、プログラムがcrashに至らないように逆シーケンス化されたnullオブジェクトをフィルタリングする必要があり、プロジェクトにはツールクラスListItemFilterがセット内のnullの要素をフィルタリングできるように提供されている.
4結語
このようなタイプの異なるJsonObjectをどのように優雅に解析するかについては、最初は考えが欠けていたが、ネット上で適切なドキュメントを調べられなかった.しかし、Gsonのドキュメントとソースコードを表示することで、自分の理解と分析を通じて、この過程を徐々に完成しました.私の1つの感触は、公式のドキュメントを多く見て、盲目的にソリューションを検索するよりも良いはずです.
コードは最高のドキュメントで、本文は簡単にいくつかの実現構想を紹介しただけで、文の中で貼ったいくつかのコードは説明の便利さのためで、プロジェクトの中のコードといくつかの違いがあるかもしれません.具体的な使用はプロジェクトの例を見ることができます.
もし問題があれば、issueや伝言を歓迎します.もしあなたに役に立つなら、スターを歓迎します.
リファレンス
Gson公式ドキュメント
public class Attribute {
...
}
public class AddressAttribute extends Attribute {
private String street;
private String city;
private String country;
... get/set
}
public class NameAttribute extends Attribute {
@SerializedName("first-name")
private String firstname;
@SerializedName("last-name")
private String lastname;
... get/set
}
gsonBuilder.registerTypeAdapter(Attribute.class, new AttributeJsonDeserializer());
"address"——AddressAttribute.class
"name"——NameAttribute.class
Attribute attribute = gson.form(addressJson,AddressAttribute.class);
public Attribute deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
{
"street": "NanJing Road",
"city": "ShangHai",
"country": "China"
}
{
"first-name": "Su",
"last-name": "Tu"
}
{
"type": "name",
"attributes": {
...
}
}
gsonBuilder.registerTypeAdapter(AttributeWithType.class, new AttributeWithTypeJsonDeserializer());
public class AttributeWithType {
private String type;
private Attribute attributes;
...
}
AttributeWithType attributeWithType = gson.fromJson(json, AttributeWithType.class);
1.プロジェクトには、外部に個別のtype要素がなく、他の要素と同じJsonObjectに配置された別のフォーマットのjsonも存在する可能性があります.このようなフォーマットは、外層のtypeAdaperを登録する必要がなく、より手間が省けます.
{
"total": 2,
"list": [
{
"type": "address",
"street": "NanJing Road",
"city": "ShangHai",
"country": "China"
},
{
"type": "name",
"first-name": "Su",
"last-name": "Tu"
}
]
}
MultiTypeJsonParser multiTypeJsonParser = new MultiTypeJsonParser.Builder()
.registerTypeElementName("type")
.registerTargetClass(Attribute.class)
// jsonObejct , Type,
// .registerTargetUpperLevelClass(AttributeWithType.class)
.registerTypeElementValueWithClassType("address", AddressAttribute.class)
.registerTypeElementValueWithClassType("name", NameAttribute.class)
.build();
ListInfoWithType listInfoWithType = multiTypeJsonParser.fromJson(TestJson.TEST_JSON_1, ListInfoWithType.class);
2.解析中にMultiTypeJsonParserのBuilderに登録されていないタイプがある場合、解析中に対応するjsonObjectに遭遇するとnullに戻ります.例えば以下のようなjsonでは,「type」に対応する「parents」が登録されていなければ,逆シーケンス化の際にこのjsonが表すオブジェクトはnullである.
{
"type": "parents",
"attributes": {
"mather": "mi lan",
"father": "lin ken"
}
}
Androidでは逆シーケンスのようなjsonの後、一般的に得られるオブジェクトの設定をリストコントロールに設定し、バックエンドで返されるjsonに以前に登録されていなかったタイプが含まれている場合、プログラムがcrashに至らないように逆シーケンス化されたnullオブジェクトをフィルタリングする必要があり、プロジェクトにはツールクラスListItemFilterがセット内のnullの要素をフィルタリングできるように提供されている.
4結語
このようなタイプの異なるJsonObjectをどのように優雅に解析するかについては、最初は考えが欠けていたが、ネット上で適切なドキュメントを調べられなかった.しかし、Gsonのドキュメントとソースコードを表示することで、自分の理解と分析を通じて、この過程を徐々に完成しました.私の1つの感触は、公式のドキュメントを多く見て、盲目的にソリューションを検索するよりも良いはずです.
コードは最高のドキュメントで、本文は簡単にいくつかの実現構想を紹介しただけで、文の中で貼ったいくつかのコードは説明の便利さのためで、プロジェクトの中のコードといくつかの違いがあるかもしれません.具体的な使用はプロジェクトの例を見ることができます.
もし問題があれば、issueや伝言を歓迎します.もしあなたに役に立つなら、スターを歓迎します.
リファレンス
Gson公式ドキュメント
Gson公式ドキュメント