带有GSON和抽象类的JSON

经过多年使用org.json库在Java中支持JSON数据交换格式后,我已切换到Google Gson 。 org.json是一个较低级的库,因此您必须创建JSONObject,JSONArray,JSONString等…并执行其他低级工作。 Gson简化了这项工作。 它提供了简单的toJson()和fromJson()方法,可将任意Java对象转换为JSON,反之亦然,支持Java泛型,允许对象的自定义表示,生成紧凑且可读性强的JSON输出,并具有许多其他优点。 我越来越喜欢它。 使用很简单。 假设我们有一个叫做Circle的类。
public class Circle {
    private int radius = 10;
    private String backgroundColor = "#FF0000";
    private String borderColor = "#000000";
    private double scaleFactor = 0.5;
    ...

    // getter / setter
}

序列化(Java对象–> JSON)可以如下进行:

Circle circle = new Circle();
Gson gson = new Gson();
String json = gson.toJson(circle); 
==> json is
{
    "radius": 10,
    "backgroundColor": "#FF0000",
    "borderColor": "#000000",
    "scaleFactor": 0.5,
    ...
}

反序列化(JSON –> Java对象)只是一行代码:

Circle circle2 = gson.fromJson(json, Circle.class);  
==> circle2 is the same as the circle above

一切都像魅力。 我只遇到抽象类一个问题。 假设,我们有一个抽象类AbstractElement和许多其他类来扩展这一类

public abstract class AbstractElement {
    private String uuid;

    // getter / setter
}

public class Circle extends AbstractElement {
   ...
}

public class Rectangle extends AbstractElement {
   ...
}

public class Ellipse extends AbstractElement {
   ...
}

现在假定,我们将所有具体类存储在使用AbstractElement参数化的列表或映射中

public class Whiteboard
{
    private Map<String, AbstractElement> elements = 
            new LinkedHashMap<String, AbstractElement>();
    ...
}

问题是在反序列化期间未公开具体类。 在Whiteboard的JSON表示中未知。 如何从JSON表示形式实例化正确的Java类并将其放入Map <String,AbstractElement>元素中? 我在文档中找不到解决该问题的方法。 显然,我们需要在有关具体类的JSON表示中存储元信息。 这是肯定的。 Gson允许您注册自己的自定义序列化器和反序列化器。 这是Gson的强大功能。 有时默认表示不是您想要的。 例如在处理第三方库类时,通常就是这种情况。 有足够的示例说明如何编写自定义序列化器/反序列化器。 我将创建一个实现两个接口JsonSerializer,JsonDeserializer的适配器类,并将其注册为我的抽象类AbstractElement。

GsonBuilder gsonBilder = new GsonBuilder();
gsonBilder.registerTypeAdapter(AbstractElement.class, new AbstractElementAdapter());
Gson gson = gsonBilder.create();

这是AbstractElementAdapter:

package com.googlecode.whiteboard.json;

import com.google.gson.*;
import com.googlecode.whiteboard.model.base.AbstractElement;
import java.lang.reflect.Type;

public class AbstractElementAdapter implements JsonSerializer<AbstractElement>, JsonDeserializer<AbstractElement> {
    @Override
    public JsonElement serialize(AbstractElement src, Type typeOfSrc, JsonSerializationContext context) {
        JsonObject result = new JsonObject();
        result.add("type", new JsonPrimitive(src.getClass().getSimpleName()));
        result.add("properties", context.serialize(src, src.getClass()));

        return result;
    }

    @Override
    public AbstractElement deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
        throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();
        String type = jsonObject.get("type").getAsString();
        JsonElement element = jsonObject.get("properties");

        try {
            return context.deserialize(element, Class.forName("com.googlecode.whiteboard.model." + type));
        } catch (ClassNotFoundException cnfe) {
            throw new JsonParseException("Unknown element type: " + type, cnfe);
        }
    }
}

我添加了两个JSON属性-一个是“类型”,另一个是“属性”。 第一个属性保存AbstractElement的具体实现类(简单名称),第二个属性保存序列化对象本身。 JSON看起来像

{
    "type": "Circle",
    "properties": {
        "radius": 10,
        "backgroundColor": "#FF0000",
        "borderColor": "#000000",
        "scaleFactor": 0.5,
        ...
    }
}

反序列化期间,我们受益于“类型”属性。 现在可以通过Class.forName(“ com.googlecode.whiteboard.model。” + type)实例化具体类,其中“ com.googlecode.whiteboard.model”。 + type是完全限定的类名。 以下通话

public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException

JsonDeserializationContext中的from会在指定对象上调用默认的反序列化并完成作业。

参考: 带有GSON的JSON和来自JCG合作伙伴 Oleg Varaksin的抽象类位于软件开发博客上。


翻译自: https://www.javacodegeeks.com/2012/04/json-with-gson-and-abstract-classes.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值