【问题标题】:Dynamic addition of fasterxml Annotation?动态添加fastxml注解?
【发布时间】:2014-10-07 02:14:34
【问题描述】:

有没有办法动态设置@JsonProperty 注解:

class A {

    @JsonProperty("newB") //adding this dynamically
    private String b;

}

或者我可以简单地重命名实例的字段吗?如果是这样,建议我一个想法。 另外,ObjectMapper 可以通过什么方式与序列化一起使用?

【问题讨论】:

  • 我看到了整个类与另一个 JSON 或类似文件的映射,而我只需要更改要修改的类的特定字段,如 @JsonProperty,如果我错过了您链接中的任何内容
  • @Jayanth 你错过了这样一个事实,即你可以以任何你想要的方式定义混合,并且只包括那些你想用作覆盖的方法、字段、注释。因此,例如,您的class A 可以是用于一个或多个目标类的混合类,以使字段“b”被序列化为“newB”。
  • @StaxMan 序列化结果可以是对象还是必须是来自writeValueAsString()String
  • @Jayanth 对不起,我不太明白你在这里问什么。如果您的意思是混入的字段或方法签名是否必须相同,是的。但听起来你可能在问别的问题。

标签: java serialization jackson fasterxml


【解决方案1】:

这是一个非常晚的答案,但如果它对您或其他人有帮助,您应该能够在运行时更改注释。检查此链接:

https://www.baeldung.com/java-reflection-change-annotation-params

修改注释可能有点乱,我更喜欢其他选项。

Mixin 是一个很好的静态选项,但如果您需要在运行时更改属性,您可以使用自定义序列化程序(或反序列化程序)。然后使用您选择的 ObjectMapper 注册您的序列化程序(现在通过 Jackson 免费提供诸如 json / xml 之类的写入格式)。以下是一些其他示例:

自定义序列化器: https://www.baeldung.com/jackson-custom-serialization

自定义反序列化器: https://www.baeldung.com/jackson-deserialization

即:

    class A {
        //        @JsonProperty("newB") //adding this dynamically
        String b;
    }

    class ASerializer extends StdSerializer<A> {

        public ASerializer() {
            this(null);
        }

        public ASerializer(Class<A> a) {
            super(a);
        }

        @Override
        public void serialize(A a, JsonGenerator gen, SerializerProvider provider) throws IOException {

            if (a == null) {
                gen.writeNull();

            } else {
                gen.writeStartObject();
                gen.writeStringField("newB", a.b);
                gen.writeEndObject();
            }
        }
    }

    @Test
    public void test() throws JsonProcessingException {
        A a = new A();
        a.b = "bbb";
        String exp = "{\"newB\":\"bbb\"}";

        ObjectMapper mapper = new ObjectMapper();

        SimpleModule module = new SimpleModule();
        module.addSerializer(A.class, new ASerializer());
        mapper.registerModule(module);

        assertEquals(exp, mapper.writeValueAsString(a));
    }

【讨论】:

    【解决方案2】:

    假设您的 POJO 类如下所示:

    class PojoA {
    
        private String b;
    
        // getters, setters
    }
    

    现在,您必须创建MixIn 接口:

    interface PojoAMixIn {
    
        @JsonProperty("newB")
        String getB();
    }
    

    简单用法:

    PojoA pojoA = new PojoA();
    pojoA.setB("B value");
    
    System.out.println("Without MixIn:");
    ObjectMapper mapper = new ObjectMapper();
    System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(pojoA));
    
    System.out.println("With MixIn:");
    ObjectMapper mapperWithMixIn = new ObjectMapper();
    mapperWithMixIn.addMixInAnnotations(PojoA.class, PojoAMixIn.class);
    System.out.println(mapperWithMixIn.writerWithDefaultPrettyPrinter().writeValueAsString(pojoA));
    

    上面的程序打印:

    Without MixIn:
    {
      "b" : "B value"
    }
    With MixIn:
    {
      "newB" : "B value"
    }
    

    【讨论】:

    • 如果类中有多个字段,是否也需要在接口中添加?
    • 您必须只提供您想要更改配置的这些方法。如果您只想更新一个属性,则只需提供一种方法。
    • Michael,感谢您的回复,但我的目的是通过修改字段名称而不是 String 来取回相同的对象,您能指导我一个解决方案吗?
    • 对不起,我不明白你的问题。您能否更新您的问题并提供显示您想要做什么的示例?
    • 是的,使用 MixIn's 我实际上可以按照您所说的进行处理,但是我可以处理对象 pojoA 并返回 mixIn pojoA 而不是来自 writeValueAsString()String
    猜你喜欢
    • 1970-01-01
    • 2015-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    相关资源
    最近更新 更多