web-dev-qa-db-ja.com

ジャクソンの逆シリアル化...予期しないトークン(END_OBJECT)、

JSON配列をJavaコレクションにジャクソンを使用して逆シリアル化しようとしています。これは昨夜尋ねたこの質問への回答に動機付けられています スーパークラスをインスタンス化して特定のサブクラスを作成できますか?指定されたパラメータに基づいてインスタンス化されます

私が得ているエラーは次のとおりです(読みやすくするために改行が追加されています):

org.codehaus.jackson.map.JsonMappingException: 
    Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'type'
    that is to contain type id  (for class sempedia.model.query.QueryValue)
 at [Source: Java.io.StringReader@325aef; line: 1, column: 175] 
    (through reference chain: sempedia.model.query.QueryProperty["values"])

私の状況はかなり複雑です。私の配列には、それ自体が配列である値を含むオブジェクトが含まれています。この配列には、オブジェクトでもあるが必ずしも同じではない値が含まれています(したがってポリモーフィズム)。

次に、JSON文字列のサンプルを示します。

[
    {
      "id":"74562",
      "uri":"http://dbpedia.org/ontology/family",
      "name":"family",
      "values":[
         {
            "id":"74563",
            "uri":"http://dbpedia.org/resource/Orycteropodidae",
            "name":"Orycteropodidae"
         }
      ],
      "selected":false
    },
    {
      "id":"78564",
      "uri":"http://dbpedia.org/ontology/someNumber",
      "name":"someNumber",
      "values":[
         {
            "lower":"45",
            "upper":"975",
         }
      ],
      "selected":true
    }
]

この(以下の)コードまたは同様のものを使用して、queryPropertiesと呼んだCollection<QueryProperty>のインスタンスであるオブジェクトを取得したいと思います。

ObjectMapper mapper = new ObjectMapper();  
Collection<QueryProperty> queryProperties = 
   queryProperties = mapper.readValue(query, 
      new TypeReference<Collection<QueryProperty>>(){});

デシリアライズのための私のクラス(私が印刷していないパブリックゲッター/セッターがあります)を以下に示します。

public class QueryProperty {    
    int id;
    String uri;
    String name;
    Set<QueryValue> values;
    String selected;
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")  
@JsonSubTypes({  
    @Type(value = ResourceQueryValue.class),  
    @Type(value = NumericQueryValue.class)
    })  
public abstract class QueryValue {
    String type;
}

ResourceQueryValue

public class ResourceQueryValue extends QueryValue{
    int id;
    String uri;
    String name;
}

NumericQueryValue同じJSONにこのタイプのオブジェクトは含まれていません。

public class NumericQueryValue extends QueryValue{
    double lower;
    double upper;
}

スタックトレースの最初の部分:

org.codehaus.jackson.map.JsonMappingException: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'type' that is to contain type id  (for class sempedia.model.query.QueryValue)
 at [Source: Java.io.StringReader@325aef; line: 1, column: 175] (through reference chain: sempedia.model.query.QueryProperty["values"])
    at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.Java:163)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.wrongTokenException(StdDeserializationContext.Java:240)
    at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.Java:86)
    at org.codehaus.jackson.map.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.Java:89)
13
Ankur

よくあることですが、質問を書くことで解決策を見つけることができます。だから私は2つのことをする必要があります。

まず、型情報をJSONに追加する必要があります。これは私が本当にやりたかったことではありませんが、その情報をどこかに提供する必要があると思います。

次に、QueryValueの注釈を次のように編集する必要があります。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")  
@JsonSubTypes({  
    @Type(value = ResourceQueryValue.class, name = "ResourceQueryValue"),  
    @Type(value = NumericQueryValue.class, name= "NumericQueryValue")
    })  
15
Ankur