如何在 Jackson 中为特定类配置 setter 和 getter 名称约定?

Posted

技术标签:

【中文标题】如何在 Jackson 中为特定类配置 setter 和 getter 名称约定?【英文标题】:How to configure setter and getter name convention in Jackson for a particular class? 【发布时间】:2022-01-05 02:47:33 【问题描述】:

有一个自定义命名getter 和setter 的类。在这里,它们没有“get”或“set”前缀。

这种特殊配置只需要一个类,不需要全局。

我在 Jackson 开发线程中看到一个讨论提到 @JsonPOJO 注释正是为此目的, 但我在 Jackson 的最新版本 (v2.13) 中找不到。

https://github.com/FasterXML/jackson-databind/issues/2674, https://github.com/FasterXML/jackson-databind/issues/1325

如何表达“使用名称与 JSON 中的字段完全相同的 setter”的意图?

与以下相同,但以更简洁的方式没有为每个 setter 加上 @JsonProperty@JsonSetter

class MyModel
  private String first;
  private int second;

  public String first()
    return this.first;
  

  @JsonProperty("first")
  public void first(String value)
    this.first = value;
  

  public int second()
    return this.second;
  

  @JsonProperty("second")
  public void second(int value)
    this.second = value;
  

【问题讨论】:

【参考方案1】:

您可以覆盖默认的访问器命名策略,如下所示。

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.ToString;

public class CustomPropertyNaming
    public static void main( String[] args )
        try
            /* ObjectMapper instance configuration:
             * (a) Override the default accessor naming strategy
             * (b) Set FAIL_ON_UNKNOWN_PROPERTIES to false to avoid looking for other method names as properties (eg, toString()).
             * (c) Set REQUIRE_SETTERS_FOR_GETTERS to true to handle 'toString()' being construed as a property getter */
            ObjectMapper m = new ObjectMapper();
            m.setAccessorNaming( new DefaultAccessorNamingStrategy.Provider().withGetterPrefix( "" ).withSetterPrefix( "" ) );
            m.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
            m.configure( MapperFeature.REQUIRE_SETTERS_FOR_GETTERS, true );
            
            /* Serialization */
            String json = m.writeValueAsString( MyModel.of( "ONE", 2 ) );
            System.out.println( "Serialized: " + json );
            
            /* Deserialization */
            MyModel mm = m.readValue( json, MyModel.class );
            System.out.println( "Deserialized: " + mm );
        
        catch( JsonProcessingException e )
            e.printStackTrace();
        
    
    
    @NoArgsConstructor @AllArgsConstructor(staticName = "of") @ToString
    private static class MyModel
        private String first;
        private int second;

        public String first()
            return this.first;
        

        public void first( String value )
            this.first = value;
        

        public int second()
            return this.second;
        

        public void second( int value )
            this.second = value;
        
    

运行上述类的输出

Serialized: "first":"ONE","second":2
Deserialized: CustomPropertyNaming.MyModel(first=ONE, second=2)

(我在MyModel 上使用过Lombok。你可能有你的构造函数和toString()。)

关于此解决方案的几点说明。

由于现在属性名称和访问器名称相同,Jackson 倾向于将每个零参数方法视为 getter,将每个单参数方法视为 setter。这需要处理。我在这里所做的方式是添加一些在代码 cmets 中解释的配置。 DefaultAccessorNamingStrategy.Provider 具有您可能想要探索的其他一些可配置性。

【讨论】:

谢谢库马尔。问题是,正如问题中提到的,“只有一个班级,而不是全球范围内”才需要这样做。我想要一个注释来改变特定类的反序列化。 Hi @diziaq, (a) "for only one class, not global": 如代码所示,可以只为这个类创建一个ObjectMapper (并且可能被缓存和重用)。 (b) 注释:我找不到任何用于此目的的 Jackson 注释

以上是关于如何在 Jackson 中为特定类配置 setter 和 getter 名称约定?的主要内容,如果未能解决你的问题,请参考以下文章

Java Jackson如何在自定义序列化程序中为对象使用默认序列化程序

如何在 IRSI 中为特定用户配置触发器

如何在intelliJ IDEA中为我现有的Kotlin项目生成build.gradle文件

Jackson忽略空字段

你能配置 Spring 控制器特定的 Jackson 反序列化吗?

利用Jackson封装常用JsonUtil工具类