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

How to configure setter and getter name convention in Jackson for a particular class?

有一个 class 自定义命名的 getters 和 setters。这里他们没有“get”或“set”前缀。

只有一个 class 需要这种特殊配置,而不是全局需要。

I see a discussion in Jackson development thread mentioning @JsonPOJO annotation exactly for this purpose, but I don't find it in the latest version (v2.13) of Jackson.

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

与以下相同,但以更简洁的方式没有为每个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;
  }
}

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

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;
        }
    }
}

以上运行的输出class

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

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

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

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