2017-04-25 11 views
1

同じフィールドにブールとオブジェクトの両方を扱う、それはこのようなデータを返します。どのようにJavaのジャクソンはデシリアライザ私はサードパーティJSON APIで働いている

私は、このJSON文字列をデシリアライズするためにJavaジャクソンを使用

{details: {...}, ...}

POJOオブジェクトに、フィールド宣言は、次のとおり

@JsonProperty("details") public Details getDetails(){...}

Detailsが別のクラスです。私はそのAPIは、このようなデータを返すことが見つけるまで

すべてが正常である:

{details: false, ...}

詳細が空の場合、それはfalseを返します!!!ジャクソンは私にこの例外を与えた:

com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class Details] from Boolean value; no single-boolean/Boolean-arg constructor/factory method (through reference chain: ...["details"])

をので、JSON文字列のこの種をどのように扱いますか?空の場合は、このフィールドをnullに設定する必要があります。

+1

はとき '詳細はnullを返して、あなたのPOJOにカスタムデシリアライザをお試しくださいs'はブール値であり、そうでなければオブジェクトを返す。 – nonconvergent

答えて

2

ジャクソンからのエラーメッセージは、ライブラリは、静的ファクトリメソッドのサポートにエージェントbulitしていることを示唆しています。

public class Details { 
    public String name; // example property 

    @JsonCreator 
    public static Details factory(Map<String,Object> props) { 

     if (props.get("details") instanceof Boolean) return null; 

     Details details = new Details(); 
     Map<String,Object> detailsProps = (Map<String,Object>)props.get("details"); 
     details.name = (String)detailsProps.get("name"); 
     return details; 
    } 
} 

試験方法:

public static void main(String[] args) 
{ 
    String fullDetailsJson = "{\"details\": {\"name\":\"My Details\"}} "; 
    String emptyDetailsJson = "{\"details\": false} "; 
    ObjectMapper mapper = new ObjectMapper(); 
    try { 
     Details details = mapper.readValue(fullDetailsJson, Details.class); 
     System.out.println(details.name); 
     details = mapper.readValue(emptyDetailsJson, Details.class); 
     System.out.println(details); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
ジャクソンはそれを使用するように注釈を付け、

私はこの例POJOを作成し、静的なファクトリメソッドを持つ:これは(おそらく)カスタムデシリアライザよりも単純なソリューションです。

予想通りの結果は次のとおりです。

My Details 
null 
1

Detailsオブジェクトのデシリアライズを処理するカスタムJsonDeserializerを作成します。このオブジェクトでは、falseが返された場合はnullを返し、オブジェクトが実際のオブジェクトの場合はデフォルトのデシリアライザに渡します。擬似コード:

public class CustomDeserializer extends JsonDeserializer<Details>{ 
    @Override 
    public Details deserialize(JsonParser jsonParser, DeserializationContext ctx){ 
     //if object use default deserializer else return null 
    } 
} 

あなたはまた、そうのようなあなたのデシリアライザを登録するObjectMapperProviderを記述する必要があります:

@Provider 
public class ObjectMapperProvider implements ContextResolver<ObjectMapper>{ 
    private ObjectMapper mapper; 

    public ObjectMapperProvider(){ 
     mapper = new ObjectMapper(); 
     SimpleModule sm = new SimpleModule(); 
     sm.addDeserializer(Details.class, new CustomDeserializer()); 
     mapper.registerModule(sm); 
    } 

    public ObjectMapper getContext(Class<?> arg0){ 
     return mapper; 
    } 
} 
関連する問題