Json解析工具的缺陷与可改进点

今天遇到一个Json反序列化的问题,反序列化的对象都是别人封装好的,类似下面的例子:
有一个待序列化的Company类,它持有一个People列表。

class Company {
    List<People> peoples;

    /**
     * 构造函数.
     * 
     * @param peoples
     */
    public Company(List<People> peoples) {
        this.peoples = peoples;
    }
    。。。若干getter/setter方法

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        if (peoples != null && peoples.size() > 0) {
            String str = "";
            for (People people : peoples) {
                str += people.toString();
            }
            return str;
        }
        return super.toString();
    }
}
interface People {
}

class Man implements People {
    private String name;

    private int age;

    /**
     * 构造函数.
     * 
     * @param name
     * @param age
     */
    public Man(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "name : " + name + " age : " + age;
    }
    。。。若干getter/setter方法
}

测试用例:

        Company company = new Company(new ArrayList<People>());
        company.getPeoples().add(new Man("better future", 20));

        Gson gson = new Gson();
        String jsonString = gson.toJson(company);
        System.out.println(jsonString);
        Company company1 = gson.fromJson(jsonString, Company.class);
        System.out.println(company1);

看着没有问题,但是

Exception in thread “main” java.lang.RuntimeException: Unable to invoke no-args constructor for interface better517na.People. Register an InstanceCreator with Gson for this type may fix this problem.

Why?不能执行People的无参构造函数?People是接口呀,哪来的构造函数?这就是问题的所在了,幸好Gson提供了一种解决办法,实现一个People类的TypeAdapter来完成了People的序列化。
如下:

class PeopleTypeAdapter implements JsonSerializer<People>, JsonDeserializer<People> {
    @Override
    public People deserialize(JsonElement arg0, Type arg1, JsonDeserializationContext arg2) throws JsonParseException {
        Gson gson = new Gson();

        return gson.fromJson(arg0, Man.class);
    }

    @Override
    public JsonElement serialize(People arg0, Type arg1, JsonSerializationContext arg2) {
        Gson gson = new Gson();

        return gson.toJsonTree(arg0);
    }
}

测试代码:

        Company company = new Company(new ArrayList<People>());

        company.getPeoples().add(new Man("better future", 20));

        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(People.class, new PeopleTypeAdapter());

        Gson gson = builder.create();
        // Gson gson = new Gson();
        String jsonString = gson.toJson(company);
        System.out.println(jsonString);
        Company company1 = gson.fromJson(jsonString, Company.class);
        System.out.println(company1);

运行结果:

{“peoples”:[{“name”:”better future”,”age”:20}]}
name : better future age : 20

这里在Company反序列化时,我指定了People的实现类Man。那么问题来了,这样真的好吗?易于扩展吗?我们在Company中使用People接口,而不指定具体的实现类不就是为了扩展性吗?现在好了,管他序列化之前使用的是哪个People,一股脑全使用Man。怎么办呢?我们可以为People的每个实现类实现一个TypeAdapter呀!!这样真的好吗?说好的可扩展呢?
对此,我找了很多其他的Json序列化工具,对于这个问题,解决的办法大同小异。比较方便的是在反序列化时,指定需要特别注意的字段的Class类型,当然也有人说,我们不用接口呀!但你使用的第三方库呢?你能保证吗?
这个导致了我想到一个更近一步的解决方案,由我们先构造出反序列化的对象,然后将它传给Json工具,由Json工具将JsonString中的信息保存到我们构造的对象中,这样Json工具的职责就更明确了,负责json的序列化或反序列化,而不是构造对象。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值