【问题标题】:Can Jackson automatically treat any constructor parameter as a JsonProperty?Jackson 可以自动将任何构造函数参数视为 JsonProperty 吗?
【发布时间】:2022-01-13 20:54:19
【问题描述】:

如何让 Jackson 将“名称”视为具有 @JsonProperty 注释?

public class SimpleClass {
    private String name;
    private String doNotSerialize;

    public SimpleClass( @JsonProperty("name") String name ) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
    
    public int getSum() {
        return 1+1;
    }
}

现在的情况,我收到一个错误,无法识别字段“sum”,因为它将每个 getter 都视为可序列化的属性。

如果我添加一个类注释:

@JsonAutoDetect( getterVisibility = JsonAutoDetect.Visibility.NONE )

序列化时我得到一个空字符串。我希望 Jackson 会在构造函数参数上看到 @JsonProperty 并弄清楚。

如果我将类注释更改为:

@JsonAutoDetect( getterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.ANY )

然后我得到包含的“doNotSerialize”字段。

如果我在构造函数上设置@JsonCreator,并更改我的自动检测,我仍然会得到一个空白字符串:

@JsonAutoDetect( getterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY )
public class SimpleClass {
    private String name;
    private String doNotSerialize;

    @JsonCreator
    public SimpleClass( @JsonProperty("name") String name ) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
    
    public int getSum() {
        return 1+1;
    }
}

我希望以某种方式告诉 Jackson 将所有构造函数参数视为可序列化字段,而将所有其他字段/设置器视为不可序列化。

【问题讨论】:

  • 你在getSum上试过@JsonIgnore吗?
  • 我知道这行得通,但在我的实际项目中,我有数百个类,每个类都有未知数量的 getXXX 方法,我不想序列化。如果我添加 getXXX() 而不记得添加 @JsonIgnore,它将在运行时中断,因为当我尝试反序列化时,会抛出错误,因为构造函数中没有“sum”属性。我试图避免创建一个可能在运行时失败的编程陷阱。
  • 您是否考虑过拥有 SimpleClass(仅限数据)和 SimpleClassWrapper(派生的 getter,例如 getSum(),在其构造函数中采用 SimpleClass)。这样你就可以在你的代码中使用 SimpleClass 进行序列化和 SimpleClassWrapper 来简化/重用你的派生 getter 的代码。

标签: java json jackson


【解决方案1】:

您可以使用过滤器仅序列化具有匹配字段的 getter,例如

package org.example;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;

import java.io.IOException;
import java.io.StringWriter;


public class App {
    @JsonFilter("test")
    public static class SimpleClass {
        private String name;
        private String doNotSerialize;

        public SimpleClass(String name ) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public int getSum() {
            return 1+1;
        }
    }
    public static void main( String[] args ) throws IOException {
        SimpleFilterProvider filterProvider = new SimpleFilterProvider();
        filterProvider.addFilter("test", new SimpleBeanPropertyFilter() {
            @Override
            protected boolean include(BeanPropertyWriter writer) {
                return super.include(writer);
            }

            @Override
            protected boolean include(PropertyWriter writer) {
                String name = writer.getName();
                Class clazz = writer.getMember().getDeclaringClass();
                try {
                    clazz.getDeclaredField(name);
                    return super.include(writer);
                } catch (NoSuchFieldException e) {
                    // ignore
                    return false;
                }
            }
        });
        ObjectMapper mapper = new ObjectMapper();
        mapper.setFilterProvider(filterProvider);
        StringWriter sw = new StringWriter();
        mapper.createGenerator(sw).writeObject(new SimpleClass("foo"));
        System.out.println(sw.toString());
    }
}

我不知道您的全部要求,但这应该是一个开始。

我并没有尝试做你实际询问的事情,即查看构造函数参数,但这也应该是可能的。

【讨论】:

    【解决方案2】:

    如果您希望“sum”包含在 serializad json 中,但想在反序列化时忽略它,您可以这样做:

    @JsonIgnoreProperties(ignoreUnknown=true)
    public class SimpleClass { 
       // properties/getters 
    
       public int getSum() { return 1+1; }
    }
    

    如果你想完全从 json 中删除“sum”,你可以这样做

    @JsonIgnoreProperties({"sum"})
    public class SimpleClass { 
       // properties/getters 
    
       public int getSum() { return 1+1;  }
    }
    

    public class SimpleClass { 
       // properties/getters 
    
       @JsonIgnore
       public int getSum() { return 1+1;  }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-04-20
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 2018-04-30
      相关资源
      最近更新 更多