使用 Gson 自定义反序列化
Custom deserialization with Gson
我一直在努力改进我的代码,但不知道如何,我得到的 json 是这样的:
{
"name": "Jhon",
"lastName": "Smith",
"clothes": {
"gender":"male",
"Shirt": {
"id": 113608,
"name": "Green Shirt",
"size": "Large"
},
"Pants": {
"id": 115801,
"name": "Black Leather Pants",
"size": "Large"
}
}
}
到目前为止,它的工作方式是同时拥有衬衫和裤子 class,但由于它们是相同的,所以我尝试只使用一件 class 来获得两者 them.I没有人说 json 是如何生成的,所以必须在它出现时使用它。
这是我的 classes:
Class个人
public class Person{
private String lastName;
private String name;
private Clothes clothes;
}
Class衣服
public class Clothes{
private Shirt Shirt;
private Pants pants;
private String gender;
}
Class 衬衫
public class Shirt{
private String id;
private String name;
private String size;
}
裤子和衬衫一样,问题是我不希望我的代码被破坏if/when他们决定添加另一件衣服,所以我正在尝试做这样的事情
Class衣服
public class Clothes{
private List<Something> clothList;
private String gender;
}
不要使用 2 个单独的 classes(Shirt
和 Pants
),只需使用一个 class - 让我们说 Cloth
。试了一下,效果很好:
人class:
package com.dominikangerer.q29550820;
public class Person {
private String name;
private String lastName;
private Clothes clothes;
}
衣服class:
package com.dominikangerer.q29550820;
public class Clothes {
private String gender;
private Cloth Shirt;
private Cloth Pants;
}
布料class:
package com.dominikangerer.q29550820;
public class Cloth {
private Integer id;
private String name;
private String size;
}
在构建这些 classes 之后,我直接在一个小的 main class 中尝试了它,这导致了一个非常好的反序列化。
Gson g = new Gson();
Person person = g.fromJson("{\"name\":\"Jhon\",\"lastName\":\"Smith\",\"clothes\":{\"gender\":\"male\",\"Shirt\":{\"id\":113608,\"name\":\"Green Shirt\",\"size\":\"Large\"},\"Pants\":{\"id\":115801,\"name\":\"Black Leather Pants\",\"size\":\"Large\"}}}", Person.class);
这里没有使用 @Expose
或 @SerializedName("something")
因为不需要。
希望它能帮到你 - 否则请更详细地解释你的问题,我会尽力帮助你。
------------更新------------
好吧,通常很容易投出一个 Json,因为你在正常的 Object
中有它 - 但东西在地图内部 (clothes
) 你也有一个正常 String
值。为此,我建议您启用 Gson
功能 @Expose
我稍后会告诉您为什么这是个好主意。
让我们开始吧:
我用 Map<String, Object>
删除了 Clothes
class,Gson
可以轻松反序列化 - 这里的问题是我们在该地图中也有性别。我修改了 Person class,现在它是这样工作的:
人 v2:
package com.dominikangerer.q29550820;
public class Person {
private String name;
private String lastName;
@SerializedName("clothes")
private Map<String, Object> clothesWrapper;
public String getGender() {
return clothesWrapper.get("gender").toString();
}
public void setGender(String gender) {
this.clothesWrapper.put("gender", gender);
}
}
现在我们已经可以将 gender
映射为 String
并用 getter 和 setter 对其进行修改 - 上面仍然有包含 Object
秒。接下来我们不想要 Map<String, Object>
- 对于反序列化和序列化它完全没问题 - 但对于使用 Cloth
s 本身 - 它很愚蠢所以让我们用最简单的方法摆脱它:
我们像这样修改我们的 Person class:
人 v3:
package com.dominikangerer.q29550820;
public class Person {
@Expose
private String name;
@Expose
private String lastName;
@Expose
@SerializedName("clothes")
private Map<String, Object> clothesWrapper;
private Map<String, Cloth> clothes;
public String getGender() {
return clothesWrapper.get("gender").toString();
}
public void setGender(String gender) {
this.clothesWrapper.put("gender", gender);
}
public Map<String, Cloth> getClothes() {
if (clothes == null) {
Gson g = new Gson();
clothes = new HashMap<String, Cloth>();
for (Entry<String, Object> entry : clothesWrapper.entrySet()) {
if (entry.getKey().equals("gender")) {
continue;
}
String helper = g.toJson(entry.getValue());
Cloth cloth = g.fromJson(helper, Cloth.class);
clothes.put(entry.getKey(), cloth);
}
}
return clothes;
}
}
如您所见,我们现在间接转换所有 Cloth
es - 我们必须这样做,因为这是将所有 LinkedTreeMap
转换为 Cloth
的最简单方法-Object
没有 运行 变成了 ClassCastException
。如您所见,我们现在有一个 Map<String,Object> clothesWrapper
让 Gson 解析对象(找不到更好的名称 - 抱歉)和没有 Expose 的 Map<String, Cloth> clothes
映射。现在您还需要使用 enableExpose 选项设置 Gson,其工作方式如下:
(在这里使用 Person v3 Class - 只需调试它 - 就像一个魅力)
public class Main {
public static void main(String[] args) {
Gson g = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Person person = g.fromJson("{\"name\":\"Jhon\",\"lastName\":\"Smith\",\"clothes\":{\"gender\":\"male\",\"Shirt\":{\"id\":113608,\"name\":\"Green Shirt\",\"size\":\"Large\"},\"Pants\":{\"id\":115801,\"name\":\"Black Leather Pants\",\"size\":\"Large\"}}}", Person.class);
System.out.println(person.getClothes());
System.out.println(person.getGender());
}
}
您可以在 github repository
中找到所有 class
我一直在努力改进我的代码,但不知道如何,我得到的 json 是这样的:
{
"name": "Jhon",
"lastName": "Smith",
"clothes": {
"gender":"male",
"Shirt": {
"id": 113608,
"name": "Green Shirt",
"size": "Large"
},
"Pants": {
"id": 115801,
"name": "Black Leather Pants",
"size": "Large"
}
}
}
到目前为止,它的工作方式是同时拥有衬衫和裤子 class,但由于它们是相同的,所以我尝试只使用一件 class 来获得两者 them.I没有人说 json 是如何生成的,所以必须在它出现时使用它。
这是我的 classes:
Class个人
public class Person{
private String lastName;
private String name;
private Clothes clothes;
}
Class衣服
public class Clothes{
private Shirt Shirt;
private Pants pants;
private String gender;
}
Class 衬衫
public class Shirt{
private String id;
private String name;
private String size;
}
裤子和衬衫一样,问题是我不希望我的代码被破坏if/when他们决定添加另一件衣服,所以我正在尝试做这样的事情
Class衣服
public class Clothes{
private List<Something> clothList;
private String gender;
}
不要使用 2 个单独的 classes(Shirt
和 Pants
),只需使用一个 class - 让我们说 Cloth
。试了一下,效果很好:
人class:
package com.dominikangerer.q29550820;
public class Person {
private String name;
private String lastName;
private Clothes clothes;
}
衣服class:
package com.dominikangerer.q29550820;
public class Clothes {
private String gender;
private Cloth Shirt;
private Cloth Pants;
}
布料class:
package com.dominikangerer.q29550820;
public class Cloth {
private Integer id;
private String name;
private String size;
}
在构建这些 classes 之后,我直接在一个小的 main class 中尝试了它,这导致了一个非常好的反序列化。
Gson g = new Gson();
Person person = g.fromJson("{\"name\":\"Jhon\",\"lastName\":\"Smith\",\"clothes\":{\"gender\":\"male\",\"Shirt\":{\"id\":113608,\"name\":\"Green Shirt\",\"size\":\"Large\"},\"Pants\":{\"id\":115801,\"name\":\"Black Leather Pants\",\"size\":\"Large\"}}}", Person.class);
这里没有使用 @Expose
或 @SerializedName("something")
因为不需要。
希望它能帮到你 - 否则请更详细地解释你的问题,我会尽力帮助你。
------------更新------------
好吧,通常很容易投出一个 Json,因为你在正常的 Object
中有它 - 但东西在地图内部 (clothes
) 你也有一个正常 String
值。为此,我建议您启用 Gson
功能 @Expose
我稍后会告诉您为什么这是个好主意。
让我们开始吧:
我用 Map<String, Object>
删除了 Clothes
class,Gson
可以轻松反序列化 - 这里的问题是我们在该地图中也有性别。我修改了 Person class,现在它是这样工作的:
人 v2:
package com.dominikangerer.q29550820;
public class Person {
private String name;
private String lastName;
@SerializedName("clothes")
private Map<String, Object> clothesWrapper;
public String getGender() {
return clothesWrapper.get("gender").toString();
}
public void setGender(String gender) {
this.clothesWrapper.put("gender", gender);
}
}
现在我们已经可以将 gender
映射为 String
并用 getter 和 setter 对其进行修改 - 上面仍然有包含 Object
秒。接下来我们不想要 Map<String, Object>
- 对于反序列化和序列化它完全没问题 - 但对于使用 Cloth
s 本身 - 它很愚蠢所以让我们用最简单的方法摆脱它:
我们像这样修改我们的 Person class:
人 v3:
package com.dominikangerer.q29550820;
public class Person {
@Expose
private String name;
@Expose
private String lastName;
@Expose
@SerializedName("clothes")
private Map<String, Object> clothesWrapper;
private Map<String, Cloth> clothes;
public String getGender() {
return clothesWrapper.get("gender").toString();
}
public void setGender(String gender) {
this.clothesWrapper.put("gender", gender);
}
public Map<String, Cloth> getClothes() {
if (clothes == null) {
Gson g = new Gson();
clothes = new HashMap<String, Cloth>();
for (Entry<String, Object> entry : clothesWrapper.entrySet()) {
if (entry.getKey().equals("gender")) {
continue;
}
String helper = g.toJson(entry.getValue());
Cloth cloth = g.fromJson(helper, Cloth.class);
clothes.put(entry.getKey(), cloth);
}
}
return clothes;
}
}
如您所见,我们现在间接转换所有 Cloth
es - 我们必须这样做,因为这是将所有 LinkedTreeMap
转换为 Cloth
的最简单方法-Object
没有 运行 变成了 ClassCastException
。如您所见,我们现在有一个 Map<String,Object> clothesWrapper
让 Gson 解析对象(找不到更好的名称 - 抱歉)和没有 Expose 的 Map<String, Cloth> clothes
映射。现在您还需要使用 enableExpose 选项设置 Gson,其工作方式如下:
(在这里使用 Person v3 Class - 只需调试它 - 就像一个魅力)
public class Main {
public static void main(String[] args) {
Gson g = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Person person = g.fromJson("{\"name\":\"Jhon\",\"lastName\":\"Smith\",\"clothes\":{\"gender\":\"male\",\"Shirt\":{\"id\":113608,\"name\":\"Green Shirt\",\"size\":\"Large\"},\"Pants\":{\"id\":115801,\"name\":\"Black Leather Pants\",\"size\":\"Large\"}}}", Person.class);
System.out.println(person.getClothes());
System.out.println(person.getGender());
}
}
您可以在 github repository
中找到所有 class