【问题标题】:how to only serialize properties annotated with a custom annotation如何仅序列化使用自定义注释注释的属性
【发布时间】:2014-11-28 00:50:55
【问题描述】:

我们在整个应用程序中使用 jackson 将 Java 对象序列化和反序列化为 JSON。它工作得很好。

是否可以通过自定义序列化程序仅序列化使用自定义注释进行注释的 Java 对象的属性?

所以,给定自定义注释:

public @interface SpecialField {}

还有下面的豆子

public SomeBean {
   @SpecialField
   private Object propertyIncluded;

   private Object propertyExcluded;
}

自定义序列化程序(或某些等效机制)会如何序列化 propertyIncluded(使用普通的 jackson 对象映射器)并忽略 propertyExcluded?

我们不能在这个用例中使用标准的杰克逊注解 (@JsonIgnore),因为它会破坏我们在应用程序中的其他序列化用例。

【问题讨论】:

  • 你可以让jackson符合transient关键字,或者使用@JsonIgnore来看看:stackoverflow.com/questions/21745593/…
  • 看来你的答案可能在这里stackoverflow.com/questions/7105745/…
  • 我们不能在这个用例中使用 @JsonIgnore,因为它会破坏我们对 Jackson 序列化这些对象的其他用途。
  • 所以您只想在一个实例中使它们瞬态,而在其他实例中序列化这些字段?
  • @MarkW,在这个特定的例子中,我们只想序列化带有给定注释的字段。我们不想使用@Transient@JsonIgnore,因为它们已经被使用并且对其他地方的正常序列化有意义(应该如此)。

标签: java json jackson


【解决方案1】:

虽然这可能不是您想要的,但可以通过一些调整使杰克逊引擎以不同的方式序列化对象。在下面的示例中,我创建了两种类型的序列化程序,它们将或不会序列化标记为瞬态的字段。

import java.io.Serializable;

import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.map.ObjectMapper;

public class Test {

    public static void main(String[] args) throws Exception {
        ISerializer d = new Doesnt();
        ISerializer o = new Observes();

        SomeObject obj = new SomeObject();

        System.out.println("Doesnt: " + d.serialize(obj));

        System.out.println("Observes: " + o.serialize(obj));
    }
    public static class Doesnt implements ISerializer<SomeObject> {

        @Override
        public String serialize(SomeObject o) throws Exception {
            ObjectMapper om = new ObjectMapper();
            om.setVisibilityChecker(
                    om.getSerializationConfig().
                    getDefaultVisibilityChecker().
                    withFieldVisibility(JsonAutoDetect.Visibility.ANY).
                    withGetterVisibility(JsonAutoDetect.Visibility.ANY));
            return om.writeValueAsString(o);
        }

    }

    public static class Observes implements ISerializer<SomeObject> {

        @Override
        public String serialize(SomeObject o) throws Exception {
            ObjectMapper om = new ObjectMapper();
            om.setVisibilityChecker(
                    om.getSerializationConfig().
                    getDefaultVisibilityChecker().
                    withFieldVisibility(JsonAutoDetect.Visibility.ANY).
                    withGetterVisibility(JsonAutoDetect.Visibility.NONE));
            return om.writeValueAsString(o);
        }       
    }
    public interface ISerializer<T> {
        public String serialize(T o) throws Exception;
    }

    public static class SomeObject implements Serializable {
        private static final long serialVersionUID = 745063791749142843L;
        private transient String myVar = "Transient";
        private String myOther = "Not Transient";
        public String getMyVar() {
            return myVar;
        }
        public void setMyVar(String myVar) {
            this.myVar = myVar;
        }
        public String getMyOther() {
            return myOther;
        }
        public void setMyOther(String myOther) {
            this.myOther = myOther;
        }
    }
}

输出:

Doesnt: {"myVar":"Transient","myOther":"Not Transient"}
Observes: {"myOther":"Not Transient"}

我认为更改序列化程序以扩展 JsonSerializer 类并在其中执行类似操作会相当容易。

【讨论】:

  • 这样做(使用映射器可见性设置)需要我们对 Java 进行结构更改,将我们的代码与这个特定的序列化案例紧密耦合。这里涉及很多实体,这是一个横切关注点,因此如果可能,我们更愿意使用注释来完成它。我看到 jackson ContextualSerializer 用于检查注释,我将尝试使用它来基于自定义注释进行条件序列化。
猜你喜欢
  • 2014-11-11
  • 1970-01-01
  • 2020-07-26
  • 2019-02-14
  • 2020-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-20
相关资源
最近更新 更多