8

json からの Jackson シリアライゼーションの使用に問題があります。Collections.unmodifiableMap?

私が得るエラーは次のとおりです。

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.util.Collections$UnmodifiableMap, problem: No default constructor found

http://wiki.fasterxml.com/SimpleAbstractTypeResolverSimpleAbstractTypeResolverから使用したかったのですが、内部クラスの型を取得できませんCollections$UnmodifiableMap

Map<Integer, String> emailMap = newHashMap();
Account testAccount = new Account();
ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, As.PROPERTY);
String marshalled ;
emailMap.put(Integer.valueOf(10), "bob@mail.com");
testAccount.setMemberEmails(emailMap);

marshalled = mapper.writeValueAsString(testAccount);
System.out.println(marshalled);
Account returnedAccount = mapper.readValue(marshalled, Account.class);
System.out.println(returnedAccount.containsValue("bob@mail.com"));


public class Account {
  private Map<Integer, String> memberEmails = Maps.newHashMap();

  public void setMemberEmails(Map<Integer, String> memberEmails) {
    this.memberEmails = memberEmails;
  }

  public Map<Integer, String> getMemberEmails() {
    return Collections.unmodifiableMap(memberEmails);
  }

何か案は?前もって感謝します。

4

2 に答える 2

3

さて、ジャクソンとのエッジっぽいタイプのケースに遭遇しました。実際の問題は、ライブラリが getter メソッドを喜んで使用してコレクションとマップのプロパティを取得し、これらの getter メソッドが null を返す場合にのみ、これらのコレクション/マップのインスタンス化にフォールバックすることです。

これは、アノテーションを組み合わせることで修正できますが、JSON 出力@JsonProperty/@JsonIgnoreのプロパティが変更されるという注意事項があります。@class

コード例:

public class Account {
    @JsonProperty("memberEmails")
    private Map<Integer, String> memberEmails = Maps.newHashMap();

    public Account() {
        super();
    }

    public void setMemberEmails(Map<Integer, String> memberEmails) {
        this.memberEmails = memberEmails;
    }

    @JsonIgnore
    public Map<Integer, String> getMemberEmails() {
        return Collections.unmodifiableMap(memberEmails);
    }
}

このクラスをテスト コードでシリアル化すると、次の JSON が得られます。

{
    "@class": "misc.stack.pojo.Account",
    "memberEmails": {
        "10": "bob@mail.com",
        "@class": "java.util.HashMap"
    }
}

これは正しく逆シリアル化されます。

于 2013-07-12T15:15:54.840 に答える
0

Jackson が最初に探すのは、デフォルトのコンストラクターです。@JsonCreator別のコンストラクターを使用する場合は、そのコンストラクターに add を指定し、そのパラメーターに@JsonProperty注釈を指定する必要があります。

これらの注釈を追加する機能Collections.UnmodifiableCollectionがないため、逆シリアル化することはできません。

  1. シリアル化するために変更不可能なコレクションを使用する必要はないでしょう。ポイントは?オブジェクトを逆シリアル化するときにそれを行うことができます。また、逆シリアル化されたオブジェクトは、シリアル化 (コピー) されたオブジェクトとは異なります

  2. 本当に必要な場合は、独自のUnmodifiableCollectionクラスを作成するだけです。コレクションの単なるラッパーであり、メソッド呼び出しを基になるコレクションに委譲するため、非常に単純です。

    public boolean isEmpty() { return c.isEmpty(); } // c is underlying collection
    

    メソッドの変更を除いて:

    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }
    .....
    
  3. シリアル化の前にいずれかのメソッドを呼び出して、配列をシリアル化することもできます。デシリアライズするときは、配列からコレクションを作成してオブジェクトをモデル化し、変更不可能なコレクションを返す getter でこのコレクションにアクセスします。

    public Object[] toArray();
    public <T> T[] toArray(T[] a);
    
  4. @JsonIgnoreモデルの getter メソッドに追加@JsonValueして、フィールドに追加できますmemberEmails

  5. 別のゲッター(プライベートで別の名前)を作成@JsonValueし、フィールドのように注釈を付けることができます

于 2013-07-12T10:28:01.313 に答える