developer tip

잭슨 : 부동산이 없으면 어떻게 되나요?

copycodes 2020. 12. 12. 11:28
반응형

잭슨 : 부동산이 없으면 어떻게 되나요?


생성자 매개 변수에 주석을 달았 @JsonProperty지만 Json이 해당 속성을 지정하지 않으면 어떻게됩니까 ? 생성자는 어떤 값을 얻습니까?

null 값이있는 속성과 JSON에없는 속성을 어떻게 구별합니까?


프로그래머 BruceStaxMan의 훌륭한 답변 요약 :

  1. 생성자가 참조하는 누락 된 속성 에는 Java에서 정의한 기본값이 할당 됩니다 .

  2. setter 메서드를 사용하여 암시 적으로 또는 명시 적으로 설정된 속성을 구분할 수 있습니다. Setter 메서드는 명시 적 값이있는 속성에 대해서만 호출됩니다. Setter 메서드는 속성이 부울 플래그 (예 :)를 사용하여 명시 적으로 설정되었는지 여부를 추적 할 수 있습니다 isValueSet.


@JsonProperty를 사용하여 생성자 매개 변수에 주석을 달았지만 Json이 해당 속성을 지정하지 않으면 어떻게됩니까? 생성자는 어떤 값을 얻습니까?

이와 같은 질문에 대해서는 샘플 프로그램을 작성하고 무슨 일이 일어나는지 보는 것을 좋아합니다.

다음은 그러한 샘플 프로그램입니다.

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

그 결과 생성자에 데이터 유형의 기본값이 전달됩니다.

null 값이있는 속성과 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:

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


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.

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


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)?


(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:

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


another option is to validate the object after deserialization either manually or via frameworks such java bean validation or, if you are using spring, the spring validation support.

참고URL : https://stackoverflow.com/questions/8320993/jackson-what-happens-if-a-property-is-missing

반응형