programing tip

Jackson with JSON : Unrecognized field, not mark as ignorable

itbloger 2020. 10. 3. 10:05
반응형

Jackson with JSON : Unrecognized field, not mark as ignorable


특정 JSON 문자열을 Java 개체로 변환해야합니다. JSON 처리를 위해 Jackson을 사용하고 있습니다. 입력 JSON을 제어 할 수 없습니다 (웹 서비스에서 읽음). 이것은 내 입력 JSON입니다.

{"wrapper":[{"id":"13","name":"Fred"}]}

다음은 간단한 사용 사례입니다.

private void tryReading() {
    String jsonStr = "{\"wrapper\"\:[{\"id\":\"13\",\"name\":\"Fred\"}]}";
    ObjectMapper mapper = new ObjectMapper();  
    Wrapper wrapper = null;
    try {
        wrapper = mapper.readValue(jsonStr , Wrapper.class);
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("wrapper = " + wrapper);
}

내 엔티티 클래스는 다음과 같습니다.

public Class Student { 
    private String name;
    private String id;
    //getters & setters for name & id here
}

내 래퍼 클래스는 기본적으로 내 학생 목록을 가져 오는 컨테이너 객체입니다.

public Class Wrapper {
    private List<Student> students;
    //getters & setters here
}

이 오류가 계속 발생하고 "래퍼"가을 반환합니다 null. 무엇이 누락되었는지 잘 모르겠습니다. 누군가 제발 도와 줄 수 있습니까?

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: 
    Unrecognized field "wrapper" (Class Wrapper), not marked as ignorable
 at [Source: java.io.StringReader@1198891; line: 1, column: 13] 
    (through reference chain: Wrapper["wrapper"])
 at org.codehaus.jackson.map.exc.UnrecognizedPropertyException
    .from(UnrecognizedPropertyException.java:53)

Jackson의 클래스 수준 주석을 사용할 수 있습니다.

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties
class { ... }

POJO에서 정의하지 않은 모든 속성을 무시합니다. JSON에서 몇 가지 속성 만 찾고 전체 매핑을 작성하고 싶지 않을 때 매우 유용합니다. Jackson의 웹 사이트 에서 더 많은 정보를 얻을 수 있습니다 . 선언되지 않은 속성을 무시하려면 다음과 같이 작성해야합니다.

@JsonIgnoreProperties(ignoreUnknown = true)

당신이 사용할 수있는

ObjectMapper objectMapper = getObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

선언되지 않은 모든 속성을 무시합니다.


첫 번째 대답은 거의 정확하지만 필요한 것은 필드가 아닌 getter 메서드를 변경하는 것입니다. 필드는 비공개이며 자동 감지되지 않습니다. 또한, 둘 다 표시되는 경우 게터가 필드보다 우선합니다 (개인 필드를 표시하는 방법도 있지만 게터를 사용하려는 경우 그다지 중요하지 않습니다).

따라서 getter는 이름을 지정 getWrapper()하거나 다음과 같이 주석을 달아야합니다.

@JsonProperty("wrapper")

getter 메소드 이름을 그대로 선호하는 경우.


Jackson 2.6.0을 사용하면 이것은 나를 위해 일했습니다.

private static final ObjectMapper objectMapper = 
    new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

및 설정 :

@JsonIgnoreProperties(ignoreUnknown = true)

두 가지 방법으로 달성 할 수 있습니다.

  1. 알 수없는 속성을 무시하도록 POJO 표시

    @JsonIgnoreProperties(ignoreUnknown = true)
    
  2. POJO / json을 직렬화 / 역 직렬화하는 ObjectMapper를 아래와 같이 구성합니다.

    ObjectMapper mapper =new ObjectMapper();            
    // for Jackson version 1.X        
    mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    // for Jackson version 2.X
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 
    

이것은 나를 위해 완벽하게 작동했습니다.

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(
    DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

@JsonIgnoreProperties(ignoreUnknown = true) 주석은하지 않았습니다.


이것은 모두보다 잘 작동합니다.이 속성을 참조하십시오.

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

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    projectVO = objectMapper.readValue(yourjsonstring, Test.class);

Jackson 2.0을 사용하는 경우

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

문서 에 따르면 선택한 필드 또는 모든 알 수없는 필드를 무시할 수 있습니다.

 // to prevent specified fields from being serialized or deserialized
 // (i.e. not include in JSON output; or being set even if they were included)
 @JsonIgnoreProperties({ "internalId", "secretKey" })

 // To ignore any unknown properties in JSON input without exception:
 @JsonIgnoreProperties(ignoreUnknown=true)

다음 코드로 나를 위해 일했습니다.

ObjectMapper mapper =new ObjectMapper();    
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Jackson은 클래스 Wrapper에서 "wrapper"라는 필드를 찾을 수 없기 때문에 불평하고 있습니다. 이는 JSON 개체에 "래퍼"라는 속성이 있기 때문에 수행됩니다.

수정 사항은 Wrapper 클래스의 필드 이름을 "students"대신 "wrapper"로 변경하는 것입니다.


아래 방법을 시도해 보았고 Jackson과 함께 읽는 JSON 형식에서 작동합니다. 이미 제안 된 솔루션 사용 : getter에 주석 달기@JsonProperty("wrapper")

래퍼 클래스

public Class Wrapper{ 
  private List<Student> students;
  //getters & setters here 
} 

래퍼 클래스에 대한 나의 제안

public Class Wrapper{ 

  private StudentHelper students; 

  //getters & setters here 
  // Annotate getter
  @JsonProperty("wrapper")
  StudentHelper getStudents() {
    return students;
  }  
} 


public class StudentHelper {

  @JsonProperty("Student")
  public List<Student> students; 

  //CTOR, getters and setters
  //NOTE: If students is private annotate getter with the annotation @JsonProperty("Student")
}

그러나 이것은 다음 형식의 출력을 제공합니다.

{"wrapper":{"student":[{"id":13,"name":Fred}]}}

또한 자세한 내용은 https://github.com/FasterXML/jackson-annotations참조하십시오.

도움이 되었기를 바랍니다


이 솔루션은 json 스트림을 읽을 때 일반적이며 도메인 클래스에서 올바르게 매핑되지 않은 필드는 무시할 수있는 동안 일부 필드 만 가져와야합니다.

import org.codehaus.jackson.annotate.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)

자세한 해결책은 jsonschema2pojo와 같은 도구를 사용하여 json 응답의 스키마에서 Student와 같은 필수 도메인 클래스를 자동 생성하는 것입니다. 온라인 json에서 스키마 변환기로 후자를 수행 할 수 있습니다.


json 속성과 java 속성의 이름이 일치하지 않으므로 필드 학생에게 아래와 같이 주석을 달아주십시오.

public Class Wrapper {
    @JsonProperty("wrapper")
    private List<Student> students;
    //getters & setters here
}

As no one else has mentioned, thought I would...

Problem is your property in your JSON is called "wrapper" and your property in Wrapper.class is called "students".

So either...

  1. Correct the name of the property in either the class or JSON.
  2. Annotate your property variable as per StaxMan's comment.
  3. Annotate the setter (if you have one)

Either Change

public Class Wrapper {
    private List<Student> students;
    //getters & setters here
}

to

public Class Wrapper {
    private List<Student> wrapper;
    //getters & setters here
}

---- or ----

Change your JSON string to

{"students":[{"id":"13","name":"Fred"}]}

Your input

{"wrapper":[{"id":"13","name":"Fred"}]}

indicates that it is an Object, with a field named "wrapper", which is a Collection of Students. So my recommendation would be,

Wrapper = mapper.readValue(jsonStr , Wrapper.class);

where Wrapper is defined as

class Wrapper {
    List<Student> wrapper;
}

set public your class fields not private.

public Class Student { 
    public String name;
    public String id;
    //getters & setters for name & id here
}

What worked for me, was to make the property public. It solved the problem for me.


For my part, the only line

@JsonIgnoreProperties(ignoreUnknown = true)

didn't work too.

Just add

@JsonInclude(Include.NON_EMPTY)

Jackson 2.4.0


This worked perfectly for me

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

I fixed this problem by simply changing the signatures of my setter and getter methods of my POJO class. All I had to do was change the getObject method to match what the mapper was looking for. In my case I had a getImageUrl originally, but the JSON data had image_url which was throwing the mapper off. I changed both my setter and getters to getImage_url and setImage_url.

Hope this helps.


The new Firebase Android introduced some huge changes ; below the copy of the doc :

[https://firebase.google.com/support/guides/firebase-android] :

Update your Java model objects

As with the 2.x SDK, Firebase Database will automatically convert Java objects that you pass to DatabaseReference.setValue() into JSON and can read JSON into Java objects using DataSnapshot.getValue().

In the new SDK, when reading JSON into a Java object with DataSnapshot.getValue(), unknown properties in the JSON are now ignored by default so you no longer need @JsonIgnoreExtraProperties(ignoreUnknown=true).

To exclude fields/getters when writing a Java object to JSON, the annotation is now called @Exclude instead of @JsonIgnore.

BEFORE

@JsonIgnoreExtraProperties(ignoreUnknown=true)
public class ChatMessage {
   public String name;
   public String message;
   @JsonIgnore
   public String ignoreThisField;
}

dataSnapshot.getValue(ChatMessage.class)

AFTER

public class ChatMessage {
   public String name;
   public String message;
   @Exclude
   public String ignoreThisField;
}

dataSnapshot.getValue(ChatMessage.class)

If there is an extra property in your JSON that is not in your Java class, you will see this warning in the log files:

W/ClassMapper: No setter/field for ignoreThisProperty found on class com.firebase.migrationguide.ChatMessage

You can get rid of this warning by putting an @IgnoreExtraProperties annotation on your class. If you want Firebase Database to behave as it did in the 2.x SDK and throw an exception if there are unknown properties, you can put a @ThrowOnExtraProperties annotation on your class.


The POJO should be defined as

Response class

public class Response {
    private List<Wrapper> wrappers;
    // getter and setter
}

Wrapper class

public class Wrapper {
    private String id;
    private String name;
    // getters and setters
}

and mapper to read value

Response response = mapper.readValue(jsonStr , Response.class);

This may be a very late response, but just changing the POJO to this should solve the json string provided in the problem (since, the input string is not in your control as you said):

public class Wrapper {
    private List<Student> wrapper;
    //getters & setters here
}

One other possibility is this property in the application.properties spring.jackson.deserialization.fail-on-unknown-properties=false, which won't need any other code change in your application. And when you believe the contract is stable, you can remove this property or mark it true.


Google brought me here and i was surprised to see the answers... all suggested bypassing the error ( which always bites back 4 folds later in developement ) rather than solving it until this gentleman restored by faith in SO!

objectMapper.readValue(responseBody, TargetClass.class)

is used to convert a json String to an class object, whats missing is that the TargetClass should have public getter / setters. Same is missing in OP's question snippet too! :)

via lombok your class as below should work!!

@Data
@Builder
public class TargetClass {
    private String a;
}

This may not be the same problem that the OP had but in case someone got here with the same mistake I had then this will help them solve their problem. I got the same error as the OP when I used an ObjectMapper from a different dependency as the JsonProperty annotation.

This works:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonProperty;

Does NOT work:

import org.codehaus.jackson.map.ObjectMapper; //org.codehaus.jackson:jackson-mapper-asl:1.8.8
import com.fasterxml.jackson.annotation.JsonProperty; //com.fasterxml.jackson.core:jackson-databind:2.2.3

In my case it was simple: the REST-service JSON Object was updated (a property was added), but the REST-client JSON Object wasn't. As soon as i've updated JSON client object the 'Unrecognized field ...' exception has vanished.


You should just change the field of List from "students" to "wrapper" just the json file and the mapper will look it up.

참고URL : https://stackoverflow.com/questions/4486787/jackson-with-json-unrecognized-field-not-marked-as-ignorable

반응형