Java 当用@JsonValue反序列化类时,Jackson更喜欢私有构造函数而不是@JsonCreator

Java 当用@JsonValue反序列化类时,Jackson更喜欢私有构造函数而不是@JsonCreator,java,json,jackson,Java,Json,Jackson,我有一个带有私有构造函数和静态工厂的简单类。我希望类序列化为一个数字,因此我用@JsonValue注释了字段的getter。然而,Jackson似乎更喜欢私有构造函数而不是静态工厂,即使我用@JsonCreator注释静态工厂也是如此。如果我用@JsonIgnore注释私有构造函数,它会起作用,但感觉有点不对劲 我看到一些帖子声称@JsonCreator只有在参数用@JsonProperty注释时才有效;但是,序列化为JSON对象的对象似乎就是这种情况。此对象正在序列化为数字,因此没有可提供给注

我有一个带有私有构造函数和静态工厂的简单类。我希望类序列化为一个数字,因此我用
@JsonValue
注释了字段的getter。然而,Jackson似乎更喜欢私有构造函数而不是静态工厂,即使我用
@JsonCreator
注释静态工厂也是如此。如果我用
@JsonIgnore
注释私有构造函数,它会起作用,但感觉有点不对劲

我看到一些帖子声称
@JsonCreator
只有在参数用
@JsonProperty
注释时才有效;但是,序列化为JSON对象的对象似乎就是这种情况。此对象正在序列化为数字,因此没有可提供给注释的属性

有什么我遗漏的吗

示例类:

示例测试:


实际上,若参数是Java标准类型,Jackson将用构造函数方法重写JsonCreator方法。我想说这是BasicDeserializerFactory#U HandleSingleLearGumentConstructor方法中的一个bug

所以,问题是,如果构造函数和静态工厂方法具有常规Java类型,则构造函数的优先级高于静态工厂方法。几乎没有办法解决这个问题

将创建者可见性级别设置为非私有:

@JsonAutoDetect(creatorVisibility = JsonAutoDetect.Visibility.NON_PRIVATE)
class NonNegative {
第二种方法是删除静态工厂方法并使用构造函数。我将Premissions.checkArgument移动到构造函数(它没有太多功能…如果条件不满足,只需抛出一个IllegalArgumentException):

另一种方法是使用@JsonIgnore注释,但您提到您不喜欢这种方法:)

更新我记录了一个错误:


更新解决了首选构造函数而非静态工厂方法的Jackson错误:

您是否尝试过用@JsonProperty注释选中方法的参数?我尝试过。它没有帮助..谢谢,很高兴看到这是一个错误,而不是我误解的东西,也很高兴看到它已经被解决。另一种方法是修改构造函数,使它不会被Jackson调用,例如,添加另一个参数(可能是一个伪参数)。我不认为这比
@JsonIgnore
更好。。。
package com.example;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Test;

import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class NonNegativeTest {
  private static final ObjectMapper MAPPER = new ObjectMapper();

  @Test
  public void itSerializesAndDeserializes() throws Exception {
    NonNegative nonNegative = NonNegative.checked(0.5);

    assertThat(MAPPER.readValue(MAPPER.writeValueAsString(nonNegative), NonNegative.class)).isEqualTo(nonNegative);
  }

  /* This test fails. */
  @Test(expected = JsonMappingException.class)
  public void itDoesNotDeserializeANegativeNumber() throws Exception {
    MAPPER.readValue(MAPPER.writeValueAsString(-0.5), NonNegative.class);
  }
}
@JsonAutoDetect(creatorVisibility = JsonAutoDetect.Visibility.NON_PRIVATE)
class NonNegative {
public class NonNegative {
  private final double n;

  private NonNegative(double n) {
    Preconditions.checkArgument(n >= 0.0);
    this.n = n;
  }

  @JsonValue
  public double getValue() {
    return n;
  }
}