V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
abcbuzhiming
V2EX  ›  Java

json 序列化有没有办法保存对象的类型?

  •  
  •   abcbuzhiming · 2017-07-09 12:15:25 +08:00 · 6553 次点击
    这是一个创建于 2693 天前的主题,其中的信息可能已经有所发展或是发生改变。
    最近在工作上遇到一个问题,才意识到 jdk 序列化和 json 序列化比起来,多保存了对象的类型,于是 json 序列化在遇到反序列化时,要把你反序列化得到的对象赋值给一个接口的时候,json 序列化就吃瘪了,jvm 此时往往会告诉你 json 库不知道该把你的反序列化对象转化成什么类型。而 jdk 序列化完全没有这个问题,因为 jdk 序列化后得到的流里保存了对象的真实类型,这个问题有解吗?
    20 条回复    2017-07-23 15:32:51 +08:00
    sagaxu
        1
    sagaxu  
       2017-07-09 12:21:20 +08:00
    json 不可能保存对象类型,json 反序列化的时候,你不是自己可以指定对象类型吗?
    slixurd
        2
    slixurd  
       2017-07-09 12:21:54 +08:00
    这个难道不是优势么....
    JSON 反序列化只要显式指定反序列化的 Class Reference,就可以被反序列化
    JDK 的 Serializable 最大的问题就是需要匹配上 Full-qualified name.....
    还有需要通过 Version ID 来判断版本,否则会错位....
    wwqgtxx
        3
    wwqgtxx  
       2017-07-09 12:44:04 +08:00 via iPhone
    主要是因为 json 很多的用在跨语言序列化中,要是保存了类型,怎么跨语言呢,难道再根据类型给各个语言实例化一个版本?
    yinzhili
        4
    yinzhili  
       2017-07-09 12:45:44 +08:00
    json 跨语言的啊,不同语言的类型都不一样,没法指定。
    miao1007
        5
    miao1007  
       2017-07-09 13:41:38 +08:00 via Android
    楼主需要 RPC 中的 SDL
    0915240
        6
    0915240  
       2017-07-09 13:45:18 +08:00
    序列化的时候不可能保存对象类型啊

    所以你需要在反序列化的时候去指定啊,恩,没毛病。
    DeadLion
        7
    DeadLion  
       2017-07-09 15:45:55 +08:00
    最近在用 dubbo 的时候也发现了这个问题
    消费方对于嵌套泛型无法准确反序列化 使用 json 做序列化的时候

    不过楼上有人说了,使用 Class Reference 就可以转成指定的对象了。
    zjsxwc
        8
    zjsxwc  
       2017-07-09 15:56:52 +08:00
    可以自定制个 json 类型(某个字段包含对象的类型),以及对应的序列化与反序列化方法

    其实楼主的需求最好还是用 xml 来表示,序列化可以先把对象转换为 xml 对象再转 json ; 反序列化先转为 xml 对象再转为实际对象。
    decken
        9
    decken  
       2017-07-09 16:07:27 +08:00 via iPhone
    fastjson 有这个特性
    meowu
        10
    meowu  
       2017-07-09 23:40:05 +08:00   ❤️ 1
    @decken fastjson 是坑 项目做的大的话 千万别用
    wenzhoou
        11
    wenzhoou  
       2017-07-10 07:55:13 +08:00 via Android
    abcbuzhiming
        12
    abcbuzhiming  
    OP
       2017-07-10 10:14:10 +08:00
    @wenzhoou 谢了,虽然对我的项目没啥用

    @DeadLion 我现在发现 json 序列化的坑挺大的,以前都是序列化有明确类型的对象,所以感觉不到,现在要序列化的对象,内部接口套接口,有些接口你都不知道它的具体实现是啥,这种是不是就没法应用 json 序列化了
    abcbuzhiming
        13
    abcbuzhiming  
    OP
       2017-07-10 10:18:11 +08:00
    @slixurd 你指的是类似这种 Map<Class,Class>
    但我面对的情况挺麻烦的

    Class {

    }
    abcbuzhiming
        14
    abcbuzhiming  
    OP
       2017-07-10 10:22:36 +08:00
    @slixurd 无意中发出去了,我遇到的情况是这样的类型
    public class XXXXX{
    private AAA aaa; //这个 AAA 是个 interface
    private Map<Object, Object> attributes;
    }
    jasckson 序列化这个类的对象时没有问题,但是反序列化 json 字符串到这个 XXXXX 类的时候就会吃瘪,而且这个 XXXXX 类似别人定义的,我没法改
    meepo3927
        15
    meepo3927  
       2017-07-10 10:29:33 +08:00
    json 源于描述 javascript 的对象和数据,而后广泛应用。

    所以,json 本身肯定不携带 Class 咯
    wenzhoou
        16
    wenzhoou  
       2017-07-10 11:32:04 +08:00 via Android
    这个 AAA 的实现类是固定的 AAAImpl , 还是 根据情况分为 AAAa 和 AAAb 的不同实现类?
    abcbuzhiming
        17
    abcbuzhiming  
    OP
       2017-07-10 11:51:12 +08:00
    @wenzhoou 多个,不同的实现类,而且这只是其中一个困扰点,
    另外一个 private Map<Object, Object> attributes;这个困扰点很麻烦,我发现 jackson 对反序列化 Map<String, Object>存在漏洞,什么都不设定的情况下,它把 Object 全部当 LinkHashMap 来处理,但是如果提供的字符串内容中有类似"[111,222,333]"这样的数组结构,它还是按 Map 处理,然后直接就抛异常
    wenzhoou
        18
    wenzhoou  
       2017-07-10 18:34:48 +08:00 via Android
    根据不同的情况分不同的实现类的话。如果用我链接的方法不行的话。你需要直接转成 map 然后自己根据情况,把 map 再转成对应的类。暂时没别的想法。
    decken
        19
    decken  
       2017-07-10 19:46:12 +08:00
    @meowu #10 能举个例子吗? 我用着一直没遇到啥大问题, 除了上次 1.2.29 修复安全漏洞, 限制了 autoType 对某些老版本在特定 case 下不兼容
    woshixiaohao1982
        20
    woshixiaohao1982  
       2017-07-23 15:32:51 +08:00
    @slixurd 序列化版本可以方便缓存部分失效,例如你发布了新版的程序,这样旧版留存的对象保存在 redis 里面就自动失效了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2854 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:06 · PVG 22:06 · LAX 06:06 · JFK 09:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.