json反序列化注意的问题有哪些?

阳光 2021-01-13 21:21:30 java常见问答 4564

大家在使用Json反序列化时,有几个点需要注意一下的,这样可以方便大家以后更好的使用json,那么下面我们就给大家分享一些json反序列化注意的问题。大家可以参考以下内容。

1、内部类问题

反序列化一个类的内部类时,可能会获取意想不到的结果,实例如下:

// 测试用例package com.mogu.hui.study.json;
import java.util.List;
/**
* 用于测试json序列化
* Created by yihui on 16/4/22.
*/
public class JsonHello
{
    private String name;
    private Hello hello;
    public JsonHello()
    {}
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public Hello getHello()
    {
        return hello;
    }
    public void setHello(String hello, Listuser)
    {
        Hello h = new Hello();
        h.setHello(hello);
        h.setUser(user);
        this.hello = h;
    }
    @Override
    public String toString()
    {
        return "JsonHello{" +
            "name='" + name + '\'' +
            ", hello=" + hello +
            '}';
    }
    private class Hello
    {
        String hello;
        Listuser;
        public Hello()
        {}
        public String getHello()
        {
            return hello;
        }
        public void setHello(String hello)
        {
            this.hello = hello;
        }
        public ListgetUser()
        {
            return user;
        }
        public void setUser(Listuser)
        {
            this.user = user;
        }
        @Override
        public String toString()
        {
            return "Hello{" +
                "hello='" + hello + '\'' +
                ", user=" + user +
                '}';
        }
    }
}

测试文件容下:

package com.mogu.hui.study.json;
import com.alibaba.fastjson.JSON;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import java.util.Arrays;
/**
* Created by yihui on 16/4/22.
*/
public class JsonTest
{
    private static Logger logger = LoggerFactory.getLogger(JsonTest.class);
    @Test
    public void innerClassTest()
    {
        try
        {
            JsonHello jsonHello = new JsonHello();
            jsonHello.setName("hello");
            jsonHello.setHello("innerHello", Arrays.asList("user1", "user2"));
            String str = JSON.toJSONString(jsonHello);
            logger.info("Str: {}", str);
            Object obj = JSON.parseObject(str, JsonHello.class);
            logger.info("Obj: {}", obj);
        }
        catch (Exception e)
        {
            logger.info("error: {}", e);
        }
    }
}

输出结果:

17:20:08.863 [main] INFO com.mogu.hui.study.json.JsonTest - Str: 
{"hello":{"hello":"innerHello","user":["user1","user2"]},"name":"hello"}17:21:44.425 
[main] INFO com.mogu.hui.study.json.JsonTest - Obj: JsonHello{name='hello', 
hello=null}

从上面的输出可以看出,反序列化对象的时候,出现诡异的事情,JsonHello对象的hello元素变成了 null

那么是如何产生这个问题的呢?

其实也简单,因为内部类,json反序列化的时候,无法得到该类,"hello":{"hello":"innerHello","user":["user1","user2"]} 这个串没法愉快的转换为 Hello 对象

这种问题如何避免?

不要反序列化匿名类,内部类!

2、 枚举反序列化

当序列化的对象中,包含枚举时,反序列化可能得不到你预期的结果,枚举对象变成了一个String对象, 其实和上面的问题一样,需要

package com.mogujie.service.rate.base;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* Created by yihui on 16/10/31.
*/
public class JsonTest
{
    public enum MyDay
    {
        YESDAY("SUNDAY"), TODAY("MONDAY"), TOMORROW("TUESDAY");
        private String today;
        MyDay(String today)
        {
            this.today = today;
        }
        public String getToday()
        {
            return today;
        }
        @Override
        public String toString()
        {
            return "MyDay{" +
                "today='" + today + '\'' +
                '}';
        }
    }
    class TTT
    {
        MyDay myDay;
        public TTT()
        {}
        public TTT(MyDay myDay)
        {
            this.myDay = myDay;
        }
        @Override
        public String toString()
        {
            return "TTT{" +
                "myDay=" + myDay +
                '}';
        }
    }
    private MyDay getDay()
    {
        return MyDay.TODAY;
    }
    @Test
    public void testJson()
    {
        String str = JSON.toJSONString(getDay());
        System.out.println(str);
        // 这样反序列化ok
        MyDay myDay = JSON.parseObject(str, MyDay.class);
        System.out.println(myDay);
        ListmyDayList = new ArrayList < > ();
        myDayList.add(MyDay.TODAY);
        myDayList.add(MyDay.TOMORROW);
        String str2 = JSON.toJSONString(myDayList);
        System.out.println(str2);
        // 反序列化失败, 和模板类的问题一样
        try
        {
            Listout = JSON.parseObject(str2, List.class);
            for (MyDay myDay1: out)
            {
                System.out.println(myDay1);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        // 采用这种方式,反序列化ok
        TypeReference < list > typeReference = new TypeReference < list > ()
        {};
        try
        {
            Listout = JSON.parseObject(str2, typeReference);
            for (MyDay myDay1: out)
            {
                System.out.println(myDay1);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        System.out.println("------------");
        TTT tt = new TTT(MyDay.TODAY);
        String str3 = JSON.toJSONString(tt);
        System.out.println(str3);
        // 直接反序列化异常
        try
        {
            TTT recover = JSON.parseObject(str3, TTT.class);
            System.out.println(recover);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

输出内容

"TODAY"
MyDay
{
    today = 'MONDAY'
} ["TODAY", "TOMORROW"] java.lang.ClassCastException: java.lang.String cannot be cast to com.mogujie.service.rate.base.JsonTest$MyDay
at com.mogujie.service.rate.base.JsonTest.testJson(JsonTest.java: 79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java: 57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java: 43)
at java.lang.reflect.Method.invoke(Method.java: 606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java: 47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java: 12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java: 44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java: 17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java: 271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java: 70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java: 50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java: 238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java: 63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java: 236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java: 53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java: 229)
at org.junit.runners.ParentRunner.run(ParentRunner.java: 309)
at org.junit.runner.JUnitCore.run(JUnitCore.java: 160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java: 69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java: 234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java: 74) MyDay
{
    today = 'MONDAY'
}
MyDay
{
    today = 'TUESDAY'
}-- -- -- -- -- --
{}
com.alibaba.fastjson.JSONException: create instance error, class com.mogujie.service.rate.base.JsonTest$TTT
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.createInstance(JavaBeanDeserializer.java: 116)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java: 356)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java: 135)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java: 551)
at com.alibaba.fastjson.JSON.parseObject(JSON.java: 251)
at com.alibaba.fastjson.JSON.parseObject(JSON.java: 227)
at com.alibaba.fastjson.JSON.parseObject(JSON.java: 186)
at com.alibaba.fastjson.JSON.parseObject(JSON.java: 304)
at com.mogujie.service.rate.base.JsonTest.testJson(JsonTest.java: 108)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java: 57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java: 43)
at java.lang.reflect.Method.invoke(Method.java: 606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java: 47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java: 12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java: 44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java: 17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java: 271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java: 70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java: 50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java: 238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java: 63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java: 236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java: 53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java: 229)
at org.junit.runners.ParentRunner.run(ParentRunner.java: 309)
at org.junit.runner.JUnitCore.run(JUnitCore.java: 160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java: 69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java: 234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java: 74) Caused by: java.lang.NullPointerException
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.createInstance(JavaBeanDeserializer.java: 113)
    ...29 moreDisconnected from the target VM, address: '127.0.0.1:52140', transport: 'socket'
Process finished with exit code 0

这些就是大家在使用json反序列化时需要注意的,大家要重视起来。最后大家如果想要了解更多json工具教程知识,敬请关注奇Q工具网。

推荐阅读:

java有多少基本类型?基本类型有哪些特点?

springmvc工作流程是什么?springmvc组件作用有哪些?

java怎么做出界面?实例讲解