【问题标题】:Custom Jackson JSON serialization based on parent context基于父上下文的自定义 Jackson JSON 序列化
【发布时间】:2015-06-24 19:02:15
【问题描述】:

我正在尝试根据来自父级的信息有条件地序列化子 bean。

public class Parent {
  private boolean isSecure;
  private Child child;
}

public class Child {
  String someValue;
}

基本上,如果parent.isSecure() 为真,那么我想以不同于parent.isSecure() 为假的方式序列化someValue

我的实际类比这个简单的例子复杂得多,所以我真的不想为 Parent 创建一个我需要单独维护的完整自定义序列化程序(除非你可以告诉我如何利用标准序列化用于自定义序列化程序中的Parent,而无需遍历所有属性并处理 JSON 注释、视图等。如果可以,那可能会起作用,因为我可以基于isSecure() 设置上下文属性。

我不介意为孩子编写自定义序列化程序,但我不知道如何检查父级的值。

我考虑过使用“安全”视图和“不安全”视图,我可以在整个序列化过程之外指定它们,但随后我必须检查并注释父类的许多属性才能同时在'secure' 和 'insecure' 视图(由于我不想被序列化的许多属性,我已经关闭了DEFAULT_VIEW_INCLUSION 选项)。

我尝试在我的自定义子序列化程序中访问 generator.getCurrentValue(),但它始终为空,所以我不确定它应该如何工作。

我考虑过为isSecure 编写一个自定义序列化程序,并在其中设置一个上下文属性,但我如何确定它会在孩子的自定义序列化程序之前被调用? (尽管我承认我不确定上下文属性是否真的像我假设的那样起作用。)

有什么想法吗?

【问题讨论】:

    标签: java json serialization jackson


    【解决方案1】:

    您可以创建一个特定于您的isSecure 场景的序列化程序。在子元素内使用JsonGenerator#getCurrentValue 将返回父元素。这样的事情应该允许您控制Child 的序列化,而无需修改Parent 上其他属性的序列化。

    创建一个Child 序列化程序来检查Parent 属性

    SecureChildSerializerInsecureChildSerializerJsonSerializer<Child> 的实现

    public class IsSecureChildSerializer extends JsonSerializer<Child> {
        private static final SecureChildSerializer SECURE_CHILD_SERIALIZER = new SecureChildSerializer();
        private static final InsecureChildSerializer INSECURE_CHILD_SERIALIZER = new InsecureChildSerializer();
    
        @Override
        public void serialize(Child value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            if (gen.getCurrentValue() instanceof Parent) {
                Parent parent = (Parent) gen.getCurrentValue();
                if (parent.isSecure) {
                    SECURE_CHILD_SERIALIZER.serialize(value, gen, serializers);
                } else {
                    INSECURE_CHILD_SERIALIZER.serialize(value, gen, serializers);
                }
            }
        }
    }
    

    Child 序列化程序应用于关注的属性

    public class Parent {
        public boolean isSecure;
    
        @JsonSerialize(using = IsSecureChildSerializer.class)
        public Child child;
    }
    

    【讨论】:

    • 我尝试调用 gen.getCurrentValue(),但它总是返回 null。即使通过调试器查看,我也可以查看整个 writeContext 层次结构,并且每个 _currentValue 都是空的。
    • @DavidA 你是如何注册序列化程序的?在属性或 ObjectMapper 上
    • 我通过@JsonSerialize(使用= ChildSerializer.class)指定了序列化器。我需要做一些额外的注册吗?
    • 不,不是我想的那样。仍然不知道为什么 currentValue 为空。
    • 你是在注释属性还是类?
    【解决方案2】:

    我不知道您的设计的完整长度,但恕我直言,我认为这表明设计中存在一些问题。如果对象的解析方式不同,则意味着它们本质上是不同的——在这种情况下,为什么不通过继承将它们分开呢?一种方法是:

        public class Parent {
            private Child child;
        }
    
        public class SecureChild extends Parent {
            String someValue;
        }
    
        public class InSecureChild extends Parent {
            String someValue;
        }
    

    【讨论】:

    • 类结构多级组合,不是继承也不是聚合,所以这不是一个选项。
    猜你喜欢
    • 2011-04-12
    • 2013-01-18
    • 1970-01-01
    • 2014-08-02
    • 2013-10-10
    • 2018-05-06
    • 2016-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多