web-dev-qa-db-ja.com

Jacksonを使用してジェネリックJavaオブジェクトをJSONにシリアライズする

次のクラスインスタンスをJSONに変換しようとしたとき(Jacksonを使用)

public class RPCRespond<Result> {

    private int code;
    private Result result;
    private boolean success;
    private String failureReason;

    public RPCRespond() {
        this.code = 0;
        this.success = true;
        this.result = null;
    }

    public RPCRespond(Result result) {
        this.code = 0;
        this.success = true;
        this.result = result;
    }

    public RPCRespond(int code, String failureReason) {
        this.code = code;
        this.success = false;
        this.failureReason = failureReason;
    }

    public RPCRespond(int code, String failureReason, Object... args) {
        this.code = code;
        this.success = false;
        this.failureReason = String.format(failureReason, args);
    }

    public Result getResult() {
        return result;
    }


    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getFailureReason() {
        return failureReason;
    }

    public void setFailureReason(String failureReason) {
        this.failureReason = failureReason;
    }

    public int getCode() {
        return code;
    }

    public boolean getSuccess() {
        return success;
    }

    @Transient
    public String getAsJSON() {

        String json = "";

        ObjectMapper mapper = new ObjectMapper();
        json = mapper.writeValueAsString(this) ; 

        return json ;
    }

}

それは無限ループに入ります:

 at Sun.reflect.GeneratedMethodAccessor48.invoke(Unknown Source)at 
 Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
 at Java.lang.reflect.Method .invoke(Method.Java:601)at 
 org.codehaus.jackson.map.ser.BeanPropertyWriter.get(BeanPropertyWriter.Java:483)
 at 
 org.codehaus。 jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.Java:418)
 at 
 org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.Java:150)
 at 
 org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.Java:112)
 at 
 org.codehaus.jackson.map.ser .StdSerializerProvider._serializeValue(StdSerializerProvider.Java:610)
 at 
 org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.Java:256)
 at 
 org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapp er.Java:2566)
 at 
 org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.Java:2088)

RPCRespondの開始は、

User u = new User() ;
u.setFirstName("aaaa") ;
RPCRespond<User> result = new RPCRespond<User>(u) ;

result.setSuccess(true) ;

return result.getAsJSON() ;

RPCRespondをJSONに変換するにはどうすればよいですか?

21
oferbu

デフォルトでは、Jacksonはgetメソッドを介してシリアル化します。 getAsJsonメソッドに到達すると、poomの無限ループになります。 @JsonIgnoreアノテーションを付けます。

@JsonIgnore
public String getAsJSON() {
    ObjectMapper mapper = new ObjectMapper();
    return mapper.writeValueAsString(this) ; 
}

プロパティのみに基づいてシリアル化するようにJacksonを構成することもできます。これにより、@JsonIgnoreの必要性がなくなる可能性がありますが、それでニーズが満たされる場合と満たされない場合があります。

I believe最新のジャクソンでは、Hibernate @Transientアノテーションの使用を選択できますが、設定方法は不明です(最近の変更)。

57
Dave Newton

他の人が示唆しているように、これはおそらく循環参照によるものです。デフォルトでは、Jacksonはそのような依存関係を処理しません。

そのプロパティのシリアル化をスキップするか、または親/子タイプのリンケージの場合は、そのように注釈を付けることができます(詳細については、Jackson Wikiの「 双方向参照 エントリを参照してください)。

それが価値があることについては、ジェネリック型はこれを引き起こしません(つまり、おそらくここでは偶然です)。循環型は完全に問題ありません。

2
StaxMan