ジャクソンとJSON:認識できないフィールド、無視できるものとしてマークされていません


674

特定のJSON文字列をJavaオブジェクトに変換する必要があります。JSON処理にJacksonを使用しています。入力JSONを制御できません(Webサービスから読み取りました)。これは私の入力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)

2
私はこれがラッパークラスの作成を回避するのに役立つとわかりました。Map dummy<String,Student> = myClientResponse.getEntity(new GenericType<Map<String, Student>>(){});それからStudent myStudent = dummy.get("wrapper");
pulkitsinghal 2013

6
JSONは次のようになります。String jsonStr = "{\" students \ "\:[{\" id \ ":\" 13 \ "、\" name \ ":\" Fred \ "}]}"; REST POSTリクエストでWrapperオブジェクトを予期している場合
Dmitri Algazin 2015年


5
ちなみに、この質問に対するほとんどの回答は実際には別の質問、つまり上記のリンクに類似した質問に回答しています。
sleske 2015年

4
回答の大部分は、実際に解決するのではなく、敷物の下で問題を解決するのに役立ちます :(
NoobEditor

回答:


989

ジャクソンのクラスレベルのアノテーションを使用できます。

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties
class { ... }

POJOで定義していないすべてのプロパティを無視します。JSONでいくつかのプロパティを探しているだけで、マッピング全体を書きたくない場合に非常に便利です。詳細については、ジャクソンのウェブサイトをご覧ください。宣言されていないプロパティを無視したい場合は、次のように記述する必要があります。

@JsonIgnoreProperties(ignoreUnknown = true)

9
アリエル、これをクラスの外部で宣言する方法はありますか?
Jon Lorusso

4
私が所有していない(変更できない)クラスをシリアル化しています。1つのビューでは、特定のフィールドセットでシリアル化したいと考えています。別のビューでは、異なるフィールドセットをシリアル化したい(またはJSONのプロパティの名前を変更したい)。
ジョンロルッソ

11
私は(ignoreUnknown = true)あなたがあなたのクラスに注釈を付けるときにあなたが必要とすることを追加しなければなりません、さもなければそれは機能しません
ネクロマンサー

85
フリアン、これはOPの質問に対する正しい答えではありません。ただし、POJOで定義されていないプロパティを無視する方法をグーグルで検索し、これが最初の結果なので、人々がここに来たのではないかと思います。元の質問は、未定義のプロパティを無視することとは関係ありませんが。
Ric Jafe 2014年

5
これは非常に愚かなデフォルト設定です。APIにプロパティを追加すると、シリアル化全体が失敗します
headsvk

478

使用できます

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

宣言されていないプロパティはすべて無視されます。


5
これは私にとっては
うまくいき

1
正確に何をしているのかを少なくともコードの一部に貼り付けてください。何かを見逃している可能性があります。これを実行するか、または "@JsonIgnoreProperties(ignoreUnknown = true)"を使用して、問題を解決してください。とにかく頑張って。
Suresh、2012年

27
FWIW-このわずかに異なる列挙型をインポートする必要がありました:org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES
raf

9
^上記はジャクソンより前のバージョン2のためのものです
755

10
getObjectMapper()。disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
icfantv

126

最初の答えはほぼ正しいですが、必要なのはフィールドではなくゲッターメソッドを変更することです。フィールドはプライベートです(自動検出されません)。さらに、両方が表示されている場合、ゲッターはフィールドよりも優先されます(プライベートフィールドを表示する方法もありますが、ゲッターが必要な場合はあまり意味がありません)。

したがって、getterはと命名するか、次のようにgetWrapper()注釈を付ける必要があります。

@JsonProperty("wrapper")

ゲッターメソッド名をそのまま使用する場合。


詳しく説明してください-どのゲッターを変更または注釈する必要がありますか?
Frans

@JsonGetter( "wrapper")で注釈を付けたという意味ですか?
pedram bashiri

@pedrambashiriいいえ、つまり@JsonProperty。一方で@JsonGetter、法的別名である、それはめったにとして使用されていない@JsonPropertyゲッター、セッターとフィールドのための作品。セッターとゲッターはシグニチャーによって区別できます(1つは引数を取らず、非voidを返します;他は1つの引数を取ります)。
StaxMan 2018

これが私が探していた答えです!Jacksonのように聞こえますが、ソースJSONをPOJOにマッピングするのに問題がありますが、ゲッターにタグを付けることで一致を保証できます。ありがとう!
Andrew Kirna

90

ジャクソン2.6.0を使用して、これは私のために働いた:

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

そして設定:

@JsonIgnoreProperties(ignoreUnknown = true)

12
その構成アノテーションは不要です
neworld

クラスでObjectMapperとAnnotationの両方を構成する必要がありますか?各クラスに注釈を付ける必要がなく、objectMapperがすべてを修正すると思います。ただし、注釈を使用します。
prayagupd

同じクラスで両方の設定を行う必要はありません。また、DIを使用してのグローバルシングルトンインスタンスを取得しObjectMapperFAIL_ON_UNKNOWN_PROPERTIESプロパティをグローバルに設定することもできます。
user991710 2017

両方は必要ありませんが、どちらか一方を選択できます。
heez

58

2つの方法で達成できます。

  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) 
    

2
なぜこれが受け入れられる答えになるのでしょうか?これは、不明なプロパティを無視するように指示するだけですが、問題は、jsonをオブジェクトにラップする方法を見つけることでした。
サヤンタン

42

これは完璧に機能しました

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

@JsonIgnoreProperties(ignoreUnknown = true) 注釈はしませんでした。


2
OPの質問に回答しないため、反対票が投じられました。不明なプロパティを無視しても問題は解決しませんWrapperが、生徒のリストがnull空であるかインスタンスが空であるという問題が残ります。
Frans

37

これはすべてよりもうまく機能しますこのプロパティを参照してください。

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

期待どおりに動作しています!
MADHAIYAN M

ええ、これは私の問題を解決したものです-これはこの投稿のタイトルと一致しました。
Scott Langeberg 2016

答えは私にとってうまくいき、それは非常に簡単です。ありがとう
Akira

29

Jackson 2.0を使用している場合

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

なぜこの構成が私にとって効果がないのですか?
zhaozhi 2017

@zhaozhiジャクソンのバージョンによって異なります
Aalkhodiry

20

ドキュメントによると、選択したフィールドまたはすべての不明なフィールドを無視できます:

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

15

次のコードでうまくいきました:

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

15

セッターとゲッターを追加すると問題が解決しましたが、実際の問題はそれを解決する方法ではなく、エラーを抑制/無視する方法ではないと感じました。私はエラーを得た「認識できないフィールドが..無視としてマークされていません...

クラスの上で以下の注釈を使用しましたが、jsonオブジェクトを解析して入力を与えることができませんでした

@JsonIgnoreProperties(ignoreUnknown = true)

その後、セッターとゲッターを追加していないことに気づきました。「ラッパー」と「学生」にセッターとゲッターを追加した後、それは魅力のように機能しました。


これが実際に質問に答える唯一の答えのようです。他のすべての答えは、不明なプロパティを無視するものとしてマークしているだけですが、「ラッパー」は不明なプロパティではなく、解析しようとしているものです。
lbenedetto

14

「ラッパー」と呼ばれるクラスラッパー内のフィールドが見つからないため、ジャクソンは不平を言っています。これは、JSONオブジェクトに「ラッパー」というプロパティがあるためです。

修正は、Wrapperクラスのフィールドの名前を「学生」ではなく「ラッパー」に変更することだと思います。


ジムに感謝します。私はそれを試しました、そしてそれは問題を解決しませんでした。私はいくつかの注釈をしないのです場合、私は疑問に思って...
jshree

1
うーん、Javaで同等のデータを作成してから、Jacksonを使用してJSONで書き出すとどうなりますか。そのJSONと上記のJSONの違いは、問題の手がかりになるはずです。
ジムフェラン2010

この答えは、質問の例で私にとってうまくいきました。
sleske 2015年

14

私は以下の方法を試しましたが、ジャクソンでそのようなJSON形式の読み取りに機能します。既に提案されている解決策を使用する:ゲッターに注釈を付ける@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も参照してください。

お役に立てれば


Stackoverflowへようこそ。ヒント:{}ツールバーのシンボルを使用して、コードスニペットをフォーマットできます。
リー

11

このソリューションは、jsonストリームを読み取るときに一般的であり、一部のフィールドのみを取得する必要がありますが、ドメインクラスで正しくマップされていないフィールドは無視できます。

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

詳細なソリューションは、jsonschema2pojoなどのツールを使用して、json応答のスキーマからStudentなどの必要なドメインクラスを自動生成することです。後者は、オンラインのJSONからスキーマコンバーターで実行できます。


10

jsonプロパティとjavaプロパティの名前が一致しないため、フィールドの学生に以​​下のように注釈を付けます。

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

9

他の誰も言及していないように、私は...

問題は、JSONのプロパティが「ラッパー」と呼ばれ、Wrapper.classのプロパティが「学生」と呼ばれることです。

だから...

  1. クラスまたはJSONのプロパティの名前を修正してください。
  2. StaxManのコメントに従って、プロパティ変数に注釈を付けます。
  3. セッターに注釈を付ける(ある場合)

6

クラスフィールドをプライベートではなくパブリックに設定します。

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

2
悪い習慣-これはカプセル化を壊します。
ダウンヒル

1
聞いたことがある。
ダウンヒル

これらのフィールドを介して内部状態が変更される可能性があるため、ユーザーがクラスを使用すると、クラスが危険にさらされます。
ダウンヒル

5

私のために働いたのは、財産を公にすることでした。それは私のために問題を解決しました。


1
私のために働いた:D
TienLuong

5

どちらかを変更

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

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

----または----

JSON文字列を次のように変更します

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

5

あなたの入力

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

生徒のコレクションである「ラッパー」というフィールドを持つオブジェクトであることを示します。だから私の推薦は、

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

どこWrapperのように定義されます

class Wrapper {
    List<Student> wrapper;
}

5

新しいFirebase Androidでは、いくつかの大きな変更が導入されました。ドキュメントのコピーの下:

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

Javaモデルオブジェクトを更新する

2.x SDKと同様に、Firebase Databaseは渡さDatabaseReference.setValue()れたJavaオブジェクトをJSONに自動的に変換し、JSONをJavaオブジェクトに読み取ることができますDataSnapshot.getValue()

新しいSDKでは、JSONをでJavaオブジェクトに読み込むときDataSnapshot.getValue()に、JSONの不明なプロパティがデフォルトで無視されるようになり、が不要になりました@JsonIgnoreExtraProperties(ignoreUnknown=true)

JavaオブジェクトをJSONに書き込むときにフィールド/ゲッターを除外するために、の@Exclude代わりにアノテーションが呼び出されるようになりました@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)

JSONにJavaクラスにない追加のプロパティがある場合、ログファイルに次の警告が表示されます。

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

@IgnoreExtraPropertiesクラスに注釈を付けることで、この警告を取り除くことができます。Firebaseデータベースを2.x SDKでのように動作させ、不明なプロパティがある場合に例外をスローする場合は@ThrowOnExtraProperties、クラスに注釈を付けることができます。


4

私の部分では、唯一の行

@JsonIgnoreProperties(ignoreUnknown = true)

うまくいきませんでした。

追加するだけ

@JsonInclude(Include.NON_EMPTY)

ジャクソン2.4.0


4

これは完璧に機能しました

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

4

POJOクラスのセッターメソッドとゲッターメソッドのシグネチャを変更するだけで、この問題を修正しました。マッパーが探していたものと一致するようにgetObjectメソッドを変更するだけで済みました。私の場合、最初getImageUrlがありましたが、JSONデータには、マッパーをスローするimage_urlがありました。セッターとゲッターの両方をgetImage_urlとsetImage_urlに変更しました。

お役に立てれば。


あなたは明らかに正しい:あなたが望む名前がxxx_yyyである場合それを呼び出す方法はgetXxx_yyyとsetXxx_yyyでしょう。これは非常に奇妙ですが、機能します。
sivi 2016年

3

POJOは次のように定義する必要があります

応答クラス

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

ラッパークラス

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

値を読み取るマッパー

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

ほとんど。ないwrappersですがwrapper
Frans

@フラン・ハハ、エラーをキャッチしてくれてありがとう。コレクションには当然複数を使います。しかし、OPの質問によれば、それは単数形でなければなりません。
Dino Tw 2017

3

これは非常に遅い応答である可能性がありますが、POJOをこれに変更するだけで問題で提供されるjson文字列が解決されるはずです(入力文字列があなたの言ったようにあなたのコントロールにないため):

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

3

もう1つの可能性は、application.propertiesのこのプロパティ spring.jackson.deserialization.fail-on-unknown-properties=falseです。アプリケーションで他のコードを変更する必要はありません。契約が安定していると思われる場合は、このプロパティを削除するか、trueに設定できます。


3

これはOPと同じ問題ではない可能性がありますが、誰かが同じ間違いでここに来た場合に備えて、問題の解決に役立ちます。JsonPropertyアノテーションとして別の依存関係のObjectMapperを使用すると、OPと同じエラーが発生しました。

これは機能します:

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

動作しません:

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

ありがとう!import com.fasterxml.jackson.annotation.JsonPropertyが私のために代わりに機能しました:-)
phil

2

グーグルは私をここに連れてきて、私は答えを見て驚いていました... この紳士がSOへの信仰によって回復するまでそれを解決するのではなく、すべてエラーを回避することを提案ました(常に開発の後で4倍戻ります)。

objectMapper.readValue(responseBody, TargetClass.class)

json文字列をクラスオブジェクトに変換するために使用されます。欠落しているのTargetClassは、がパブリックgetター/ターを持つ必要があるということsetです。OPの質問スニペットにも同じものがありません!:)

ロンボク経由であなたのクラスは以下のように動作するはずです!!

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

2

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties


たぶん、さらに詳しい説明やドキュメントがいいかもしれません
ベンジ

@JsonIgnoreProperties(ignoreUnknown =真)罰金、おかげで動作します
ギリェルメ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.