Jackson 可以自动将任何构造函数参数视为 JsonProperty 吗?
Posted
技术标签:
【中文标题】Jackson 可以自动将任何构造函数参数视为 JsonProperty 吗?【英文标题】:Can Jackson automatically treat any constructor parameter as a 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 的代码。
【参考方案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;
【讨论】:
以上是关于Jackson 可以自动将任何构造函数参数视为 JsonProperty 吗?的主要内容,如果未能解决你的问题,请参考以下文章
Jackson MismatchedInputException(没有从字符串值反序列化的字符串参数构造函数/工厂方法)
为啥SqlParameter名称/值构造函数将0视为null?
使用 Jackson 从 XML 到 POJO 的反序列化问题:没有从字符串值反序列化的字符串参数构造函数/工厂方法
com.fasterxml.jackson.databind.JsonMappingException 没有从字符串值('1')反序列化的字符串参数构造函数/工厂方法