杰克逊:如果财产遗失会怎样?

时间:2021-02-19 18:02:22

What happens if I annotate a constructor parameter using @JsonProperty but the Json doesn't specify that property. What value does the constructor get?

如果我使用@JsonProperty注释构造函数参数但Json没有指定该属性会发生什么。构造函数得到什么价值?

How do I differentiate between a property having a null value versus a property that is not present in the JSON?

如何区分具有空值的属性与JSON中不存在的属性?

5 个解决方案

#1


39  

Summarizing excellent answers by Programmer Bruce and StaxMan:

总结程序员Bruce和StaxMan的优秀答案:

  1. Missing properties referenced by the constructor are assigned a default value as defined by Java.

    构造函数引用的缺失属性将分配Java定义的缺省值。

  2. You can use setter methods to differentiate between properties that are implicitly or explicitly set. Setter methods are only invoked for properties with explicit values. Setter methods can keep track of whether a property was explicitly set using a boolean flag (e.g. isValueSet).

    您可以使用setter方法来区分隐式或显式设置的属性。仅对具有显式值的属性调用Setter方法。 Setter方法可以跟踪是否使用布尔标志(例如isValueSet)显式设置属性。

#2


33  

What happens if I annotate a constructor parameter using @JsonProperty but the Json doesn't specify that property. What value does the constructor get?

如果我使用@JsonProperty注释构造函数参数但Json没有指定该属性会发生什么。构造函数得到什么价值?

For questions such as this, I like to just write a sample program and see what happens.

对于这样的问题,我想写一个示例程序,看看会发生什么。

Following is such a sample program.

以下是这样的示例程序。

import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.ObjectMapper;

public class JacksonFoo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();

    // {"name":"Fred","id":42}
    String jsonInput1 = "{\"name\":\"Fred\",\"id\":42}";
    Bar bar1 = mapper.readValue(jsonInput1, Bar.class);
    System.out.println(bar1);
    // output: 
    // Bar: name=Fred, id=42

    // {"name":"James"}
    String jsonInput2 = "{\"name\":\"James\"}";
    Bar bar2 = mapper.readValue(jsonInput2, Bar.class);
    System.out.println(bar2);
    // output:
    // Bar: name=James, id=0

    // {"id":7}
    String jsonInput3 = "{\"id\":7}";
    Bar bar3 = mapper.readValue(jsonInput3, Bar.class);
    System.out.println(bar3);
    // output:
    // Bar: name=null, id=7
  }
}

class Bar
{
  private String name = "BLANK";
  private int id = -1;

  Bar(@JsonProperty("name") String n, @JsonProperty("id") int i)
  {
    name = n;
    id = i;
  }

  @Override
  public String toString()
  {
    return String.format("Bar: name=%s, id=%d", name, id);
  }
}

The result is that the constructor is passed the default value for the data type.

结果是构造函数传递了数据类型的默认值。

How do I differentiate between a property having a null value versus a property that is not present in the JSON?

如何区分具有空值的属性与JSON中不存在的属性?

One simple approach would be to check for a default value post deserialization processing, since if the element were present in the JSON but had a null value, then the null value would be used to replace any default value given the corresponding Java field. For example:

一种简单的方法是在反序列化处理后检查默认值,因为如果元素存在于JSON中但具有空值,则null值将用于替换给定相应Java字段的任何默认值。例如:

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.ObjectMapper;

public class JacksonFooToo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);

    // {"name":null,"id":99}
    String jsonInput1 = "{\"name\":null,\"id\":99}";
    BarToo barToo1 = mapper.readValue(jsonInput1, BarToo.class);
    System.out.println(barToo1);
    // output:
    // BarToo: name=null, id=99

    // {"id":99}
    String jsonInput2 = "{\"id\":99}";
    BarToo barToo2 = mapper.readValue(jsonInput2, BarToo.class);
    System.out.println(barToo2);
    // output:
    // BarToo: name=BLANK, id=99

    // Interrogate barToo1 and barToo2 for 
    // the current value of the name field.
    // If it's null, then it was null in the JSON.
    // If it's BLANK, then it was missing in the JSON.
  }
}

class BarToo
{
  String name = "BLANK";
  int id = -1;

  @Override
  public String toString()
  {
    return String.format("BarToo: name=%s, id=%d", name, id);
  }
}

Another approach would be to implement a custom deserializer that checks for the required JSON elements. And yet another approach would be to log an enhancement request with the Jackson project at http://jira.codehaus.org/browse/JACKSON

另一种方法是实现一个自定义反序列化器,用于检查所需的JSON元素。另一种方法是在http://jira.codehaus.org/browse/JACKSON上记录杰克逊项目的增强请求

#3


11  

In addition to constructor behavior explained in @Programmer_Bruce's answer, one way to differentiate between null value and missing value is to define a setter: setter is only called with explicit null value. Custom setter can then set a private boolean flag ("isValueSet" or whatever) if you want to keep track of values set.

除了@ Programmer_Bruce的答案中解释的构造函数行为之外,区分空值和缺失值的一种方法是定义一个setter:setter仅使用显式null值调用。如果要跟踪设置的值,自定义setter可以设置一个私有布尔标志(“isValueSet”或其他)。

Setters have precedence over fields, in case both field and setter exist, so you can "override" behavior this way as well.

如果字段和setter都存在,则setter优先于字段,因此您也可以通过这种方式“覆盖”行为。

#4


3  

I'm thinking of using something in the style of an Option class, where a Nothing object would tell me if there is such a value or not. Has anyone done something like this with Jackson (in Java, not Scala, et al)?

我正在考虑使用Option类风格的东西,其中Nothing对象会告诉我是否存在这样的值。有没有人用杰克逊(Java,而不是Scala等人)做过这样的事情?

#5


0  

(My answer might be useful to some people finding this thread via google, even if it doesn't answer OPs question)
If you are dealing with primitive types which are omittable, and you do not want to use a setter like described in the other answers (for example if you want your field to be final), you can use box objects:

(我的回答可能对某些人通过谷歌找到这个帖子很有用,即使它没有回答OP问题)如果你正在处理可省略的原始类型,并且你不想使用其他描述的setter答案(例如,如果您希望您的字段为最终字段),您可以使用框对象:

public class Foo {
    private final int number;
    public Foo(@JsonProperty Integer number) {
        if (number == null) {
            this.number = 42; // some default value
        } else {
            this.number = number;
        }
    }
}

this doesn't work if the JSON actually contains null, but it can be sufficient if you know it will only contain primitives or be absent

如果JSON实际上包含null,则这不起作用,但如果您知道它只包含基元或不存在则可能就足够了

#1


39  

Summarizing excellent answers by Programmer Bruce and StaxMan:

总结程序员Bruce和StaxMan的优秀答案:

  1. Missing properties referenced by the constructor are assigned a default value as defined by Java.

    构造函数引用的缺失属性将分配Java定义的缺省值。

  2. You can use setter methods to differentiate between properties that are implicitly or explicitly set. Setter methods are only invoked for properties with explicit values. Setter methods can keep track of whether a property was explicitly set using a boolean flag (e.g. isValueSet).

    您可以使用setter方法来区分隐式或显式设置的属性。仅对具有显式值的属性调用Setter方法。 Setter方法可以跟踪是否使用布尔标志(例如isValueSet)显式设置属性。

#2


33  

What happens if I annotate a constructor parameter using @JsonProperty but the Json doesn't specify that property. What value does the constructor get?

如果我使用@JsonProperty注释构造函数参数但Json没有指定该属性会发生什么。构造函数得到什么价值?

For questions such as this, I like to just write a sample program and see what happens.

对于这样的问题,我想写一个示例程序,看看会发生什么。

Following is such a sample program.

以下是这样的示例程序。

import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.ObjectMapper;

public class JacksonFoo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();

    // {"name":"Fred","id":42}
    String jsonInput1 = "{\"name\":\"Fred\",\"id\":42}";
    Bar bar1 = mapper.readValue(jsonInput1, Bar.class);
    System.out.println(bar1);
    // output: 
    // Bar: name=Fred, id=42

    // {"name":"James"}
    String jsonInput2 = "{\"name\":\"James\"}";
    Bar bar2 = mapper.readValue(jsonInput2, Bar.class);
    System.out.println(bar2);
    // output:
    // Bar: name=James, id=0

    // {"id":7}
    String jsonInput3 = "{\"id\":7}";
    Bar bar3 = mapper.readValue(jsonInput3, Bar.class);
    System.out.println(bar3);
    // output:
    // Bar: name=null, id=7
  }
}

class Bar
{
  private String name = "BLANK";
  private int id = -1;

  Bar(@JsonProperty("name") String n, @JsonProperty("id") int i)
  {
    name = n;
    id = i;
  }

  @Override
  public String toString()
  {
    return String.format("Bar: name=%s, id=%d", name, id);
  }
}

The result is that the constructor is passed the default value for the data type.

结果是构造函数传递了数据类型的默认值。

How do I differentiate between a property having a null value versus a property that is not present in the JSON?

如何区分具有空值的属性与JSON中不存在的属性?

One simple approach would be to check for a default value post deserialization processing, since if the element were present in the JSON but had a null value, then the null value would be used to replace any default value given the corresponding Java field. For example:

一种简单的方法是在反序列化处理后检查默认值,因为如果元素存在于JSON中但具有空值,则null值将用于替换给定相应Java字段的任何默认值。例如:

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.ObjectMapper;

public class JacksonFooToo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);

    // {"name":null,"id":99}
    String jsonInput1 = "{\"name\":null,\"id\":99}";
    BarToo barToo1 = mapper.readValue(jsonInput1, BarToo.class);
    System.out.println(barToo1);
    // output:
    // BarToo: name=null, id=99

    // {"id":99}
    String jsonInput2 = "{\"id\":99}";
    BarToo barToo2 = mapper.readValue(jsonInput2, BarToo.class);
    System.out.println(barToo2);
    // output:
    // BarToo: name=BLANK, id=99

    // Interrogate barToo1 and barToo2 for 
    // the current value of the name field.
    // If it's null, then it was null in the JSON.
    // If it's BLANK, then it was missing in the JSON.
  }
}

class BarToo
{
  String name = "BLANK";
  int id = -1;

  @Override
  public String toString()
  {
    return String.format("BarToo: name=%s, id=%d", name, id);
  }
}

Another approach would be to implement a custom deserializer that checks for the required JSON elements. And yet another approach would be to log an enhancement request with the Jackson project at http://jira.codehaus.org/browse/JACKSON

另一种方法是实现一个自定义反序列化器,用于检查所需的JSON元素。另一种方法是在http://jira.codehaus.org/browse/JACKSON上记录杰克逊项目的增强请求

#3


11  

In addition to constructor behavior explained in @Programmer_Bruce's answer, one way to differentiate between null value and missing value is to define a setter: setter is only called with explicit null value. Custom setter can then set a private boolean flag ("isValueSet" or whatever) if you want to keep track of values set.

除了@ Programmer_Bruce的答案中解释的构造函数行为之外,区分空值和缺失值的一种方法是定义一个setter:setter仅使用显式null值调用。如果要跟踪设置的值,自定义setter可以设置一个私有布尔标志(“isValueSet”或其他)。

Setters have precedence over fields, in case both field and setter exist, so you can "override" behavior this way as well.

如果字段和setter都存在,则setter优先于字段,因此您也可以通过这种方式“覆盖”行为。

#4


3  

I'm thinking of using something in the style of an Option class, where a Nothing object would tell me if there is such a value or not. Has anyone done something like this with Jackson (in Java, not Scala, et al)?

我正在考虑使用Option类风格的东西,其中Nothing对象会告诉我是否存在这样的值。有没有人用杰克逊(Java,而不是Scala等人)做过这样的事情?

#5


0  

(My answer might be useful to some people finding this thread via google, even if it doesn't answer OPs question)
If you are dealing with primitive types which are omittable, and you do not want to use a setter like described in the other answers (for example if you want your field to be final), you can use box objects:

(我的回答可能对某些人通过谷歌找到这个帖子很有用,即使它没有回答OP问题)如果你正在处理可省略的原始类型,并且你不想使用其他描述的setter答案(例如,如果您希望您的字段为最终字段),您可以使用框对象:

public class Foo {
    private final int number;
    public Foo(@JsonProperty Integer number) {
        if (number == null) {
            this.number = 42; // some default value
        } else {
            this.number = number;
        }
    }
}

this doesn't work if the JSON actually contains null, but it can be sufficient if you know it will only contain primitives or be absent

如果JSON实际上包含null,则这不起作用,但如果您知道它只包含基元或不存在则可能就足够了