Jackson JSON User Group

JSON in Java the Right Way -- Action, Jackson!

Hey guys,

  I'm using Jackson 1.8.2 and trying to deserialize a json file (that I serialized with jackson).   The json is a simple HashMap<String, Pojo>, but the mapper is complaining when I try and deserialize.

org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.HashMap out of START_ARRAY token

My serialized HashMap string.....

{
"0f861a9a-0a3e-40a7-8ff3-0b83d8070876" : {
"name" : "BAR.xml",
"filePath" : "/FOO/repo/BAR.xml"
},
"f3cbb32e-b7b8-4af1-b48b-7ea393de7971" : {
"name" : "BLAH.xml",
"filePath" : "/FOO/repo/BLAH.xml"
},
"012009b6-26e9-4bc1-9050-2a4ac9546c7e" : {
"name" : "Check System.xml",
"filePath" : "/FOO/repo/Check System.xml"
}
}

I've tried 2 different ways to make this work, and both fail...

//doesn't work

cache = (Map<String,UUIDInfo>) mapper.readValue(bytes.toString(), new TypeReference<HashMap<String,UUIDInfo>>(){});

//doesn't work.
cache = (Map<String,UUIDInfo>) mapper.readValue(bytes.toString(), TypeFactory.mapType(HashMap.class, String.class, UUIDInfo.class));

Views: 3675

Comment by Tatu Saloranta on December 2, 2011 at 2:03pm

I think this is somehow related to the fact that when serializing, Java runtime does not have type information available to know values are of type UUIDInfo; rather, all it sees is something like "Map<?,?>". So if UUIDInfo has @JsonTypeInfo annotation, its type information is NOT included.

But when deserializing, you are specifying the type, in which case type information would be expected; and this causes error.

If this is the problem, you can have a look at this wiki entry, for suggestions on how to resolve the issue -- this is a sort of FAQ question, unfortunately, but also something Jackson can not solve due to Java Type Erasure.

Comment by Dick on December 2, 2011 at 2:42pm

Well, I've done a few things still without luck.

 

I added a "wrapper" class  called UUIDMap that is a simple Pojo that contains the Map<String, UUIDInfo> cache as it's member and public setters/getters.   I've also added the @JsonTypeInfo annotation to both the UUIDMap (wrapper) and the UUIDInfo pojo, which gives a json of...

{
"@class" : "com.hp.oo.studio.shared.UUIDRegistry.UUIDMap",
"cache" : {
"0f861a9a-0a3e-40a7-8ff3-0b83d8070876" : {
"@class" : "com.hp.oo.studio.shared.UUIDRegistry.UUIDInfo",
"filePath" : "/FOO/repo/BAR.xml",
"name" : "BAR.xml"
},
"f3cbb32e-b7b8-4af1-b48b-7ea393de7971" : {
"@class" : "com.hp.oo.studio.shared.UUIDRegistry.UUIDInfo",
"filePath" : "/FOO/repo/BLAH.xml",
"name" : "BLAH.xml"
},
"012009b6-26e9-4bc1-9050-2a4ac9546c7e" : {
"@class" : "com.hp.oo.studio.shared.UUIDRegistry.UUIDInfo",
"filePath" : "/FOO/repo/Check System.xml",
"name" : "Check System.xml"
}
}
}
That still doesn't deserialize with a call like...

UUIDMap map = mapper.readValue(bytes.toString(), UUIDMap.class);
The UUIDMap is very simple.
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")public class UUIDMap {
        Map<String, UUIDInfo> cache;

public Map<String, UUIDInfo> getCache() {
return cache;
}
public void setCache(Map<String, UUIDInfo> cache) {
this.cache = cache;
}
}
Comment by Tatu Saloranta on December 2, 2011 at 2:48pm

And the error message at this point is... ?

(can't be the same, since there's no JSON array anywhere in JSON)

Comment by Tatu Saloranta on December 2, 2011 at 2:51pm

Btw, no need for wrapper object necessarily; and if you didn't have @JsonTypeInfo, no need to add -- just guessing you might have had it.

Instead, easier would be to define:

  public class StringUuidMap extends HashMap<String,UUIDInfo> { }

(and/or add constructors in there)

Because then you can in fact serialize the thing right without passing explicit type information either when serializing or deserializing. This is due to inheritance relationship which retains key/value types in class code. So perhaps you could try that instead.

But knowing the error here would help to make sure we know what the exact problem is.

Comment by Dick on December 2, 2011 at 3:11pm

Here is the error now (with the wrapper still in place and the @JsonTypeInfo)

15:10:46.018 [main] DEBUG c.h.o.s.s.UUIDRegistry.UUIDRegistry - Load Cache = /home/waboring/devel/oo/infrastructure/runtime-EclipseApplication/.metadata/.plugins/com.hp.oo.studio.shared/uuidregistry.json
org.codehaus.jackson.map.JsonMappingException: Unexpected token (START_ARRAY), expected START_OBJECT: need JSON Object to contain As.PROPERTY type information (for class com.hp.oo.studio.shared.UUIDRegistry.UUIDMap)
at [Source: java.io.StringReader@4f296361; line: 1, column: 1]
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:56)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeWithType(BeanDeserializer.java:423)
at org.codehaus.jackson.map.deser.StdDeserializerProvider$WrappedDeserializer.deserialize(StdDeserializerProvider.java:460)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2395)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1595)
at com.hp.oo.studio.shared.UUIDRegistry.UUIDRegistry.<init>(UUIDRegistry.java:65)
at com.hp.oo.studio.shared.UUIDRegistry.UUIDRegistry.<clinit>(UUIDRegistry.java:37)

Comment by Tatu Saloranta on December 2, 2011 at 3:14pm

Then the JSON you included above is out-of-sync, as there are no JSON arrays? Exception points that JSON token stream contains an array start marker "[" where it would expect "{", so I am confused.

Comment by Dick on December 2, 2011 at 3:15pm

This is the json I'm trying to deserialize.  

{
"@class" : "com.hp.oo.studio.shared.UUIDRegistry.UUIDMap",
"cache" : {
"0f861a9a-0a3e-40a7-8ff3-0b83d8070876" : {
"@class" : "com.hp.oo.studio.shared.UUIDRegistry.UUIDInfo",
"name" : "BAR.xml",
"filePath" : "/FOO/repo/BAR.xml"
},
"f3cbb32e-b7b8-4af1-b48b-7ea393de7971" : {
"@class" : "com.hp.oo.studio.shared.UUIDRegistry.UUIDInfo",
"name" : "BLAH.xml",
"filePath" : "/FOO/repo/BLAH.xml"
},
"012009b6-26e9-4bc1-9050-2a4ac9546c7e" : {
"@class" : "com.hp.oo.studio.shared.UUIDRegistry.UUIDInfo",
"name" : "Check System.xml",
"filePath" : "/FOO/repo/Check System.xml"
}
}
}

Comment by Dick on December 2, 2011 at 3:16pm

And this is the exception.

org.codehaus.jackson.map.JsonMappingException: Unexpected token (START_ARRAY), expected START_OBJECT: need JSON Object to contain As.PROPERTY type information (for class com.hp.oo.studio.shared.UUIDRegistry.UUIDMap)
at [Source: java.io.StringReader@2cf2d65d; line: 1, column: 1]

 

Comment by Tatu Saloranta on December 2, 2011 at 3:45pm

Unfortunately that does not make any sense: this exception should not result from JSON shown. What environment is this on? Does it occur with Jackson serialization to a String, printing out JSON, then deserializing? Or is there some other software component handling things in between?

Comment by ajit samant on August 21, 2012 at 1:40am

Hello friend you just do this  like way

 

take one class LiveEvent

 

public class Event{

private String name;
private String filePath;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getFilePath() {
return filePath;
}

public void setFilePath(String filePath) {
this.filePath = filePath;
}

create a parse.txt file and save the json data.store in any directory.

then create a another class like this

here i am using Jackson to parse the json data.

public class GetEvents {
public static void main(String[] args)throws Exception{

File f=new File("D:/parse.txt");
InputStream is=new FileInputStream(f);
// the important bit is here..........................\/\/\/
InputStreamReader reader = new InputStreamReader(is);

StringWriter sw = new StringWriter();

char [] buffer = new char[1024 * 8];
int count ;

while( (count = reader.read(buffer)) != -1){
sw.write(buffer, 0, count);
}



ObjectMapper mapper = new ObjectMapper();
Map<String,LiveEvent> map = mapper.readValue(sw.toString(), new TypeReference<Map<String,LiveEvent>>(){});

Iterator entries = map.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
String key = (String) entry.getKey();
LiveEvent object = (LiveEvent) entry.getValue();



System.out.println("Key = " + key + ", Value = " + object.getName());


}
}
}

 

}

Comment

You need to be a member of Jackson JSON User Group to add comments!

Join Jackson JSON User Group

© 2014   Created by Tatu Saloranta.   Powered by

Badges  |  Report an Issue  |  Terms of Service