JsonMappingException

706 views
Skip to first unread message

Jon Nolan

unread,
Sep 1, 2010, 9:04:26 PM9/1/10
to BatchFB
I'm using Jackson to map BatchFB results into POJOs. This is working
successfully with FacebookBatcher.paged(...) but not with
FacebookBatcher.graph(...). With the later it throws:

JsonMappingException: Can not construct instance of
com.xyz.mapped.MappedFacebookPrivacy, problem: no suitable creator
method found
at [Source: N/A; line: -1, column: -1]
at
org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:
159)
at
org.codehaus.jackson.map.deser.StdDeserializationContext.instantiationException(StdDeserializationContext.java:
212)
at
org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromString(BeanDeserializer.java:
416)
at
org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:
291)
at
org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:
135)
at org.codehaus.jackson.map.deser.SettableBeanProperty
$FieldProperty.deserializeAndSet(SettableBeanProperty.java:326)
at
org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:
391)
at
org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:
286)
at
org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:
1568)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:
788)
at org.codehaus.jackson.map.ObjectMapper._convert(ObjectMapper.java:
1451)
at
org.codehaus.jackson.map.ObjectMapper.convertValue(ObjectMapper.java:
1435)
at
com.googlecode.batchfb.FacebookBatcher.executeGraphGroup(FacebookBatcher.java:
635)
at
com.googlecode.batchfb.FacebookBatcher.execute(FacebookBatcher.java:
531)
at com.googlecode.batchfb.FacebookBatcher
$Request.get(FacebookBatcher.java:116)

MappedFacebookPrivacy is the class of a public ivar on the class I
pass as the second parameter to FacebookBatcher.graph(...). As I said
before, this works great with FacebookBatcher.paged(...).

I've googled around a bit and saw reference to a Jackson bug that
throws with "no suitable creator method found". I wanted to ask you
Jeff if you have any quick advice before I start chasing other
solutions.

To clarify, the mapping class I'm passing to graph(...) looks
something like this:

public class MappedFacebookContent {
public MappedFacebookPrivacy privacy;

...

}

Thanks,
Jon

Jeff Schnitzer

unread,
Sep 1, 2010, 9:13:07 PM9/1/10
to bat...@googlegroups.com
Sounds like Jackson is having trouble creating an instance of
MappedFacebookPrivacy. Does it have a default constructor? Maybe the
class is not public (although I don't know if this is necessary)?

Jeff

Jon Nolan

unread,
Sep 5, 2010, 12:13:40 PM9/5/10
to BatchFB
## SOLVED ##

Sometimes you get -

"privacy": {
"description": "Friends Only",
"value": "ALL_FRIENDS"
},

Other times you get -

"privacy": "EVERYONE"

Specifically, you get the latter on albums and groups. So if you're
mapping those two content types (i.e. /me/albums) you need to have
something more like the following rather than what I described earlier
-

public class MappedFacebookAlbum {
public String privacy;

...
}

Jon

Jeff Schnitzer

unread,
Sep 5, 2010, 12:26:17 PM9/5/10
to bat...@googlegroups.com
Ah yes... "thank you Facebook"

Sigh.

Jeff

Johannes Neubarth

unread,
Mar 25, 2013, 7:54:59 AM3/25/13
to bat...@googlegroups.com
Hello,
was this issue actually solved? I have a similar problem with the location field, which can sometimes be complex or just a string. Compare those two different posts:

{"id": "321143681284995_10151485567909351",
 "from": ...
 "place": {
        "id": "503476439716854",
        "name": "Uitreiking Your Power Our Power Award 2013",
        "location": "Bibliotheektheater, Hoogstraat 110, Rotterdam ",
      }...

versus

{"id": "198513236845000_10151270812121263",
 "from": ...
 "place": {
    "id": "198513236845000",
    "name": "Berliner Fernsehturm",
    "location": {
      "street": "Panoramastr. 1A",
      "city": "Berlin",
      "state": "",
      "country": "Germany",
      "zip": "10178",
      "latitude": 52.521222273412,
      "longitude": 13.412083153837
    } ...

Now I don't know how to implement my Place class, since I cannot have two fields with the same name:
        // @JsonProperty("location")
        public Location location;
        // @JsonProperty("location")
        public String location;

Any help would be very appreciated.
Hannes


Jeff Schnitzer

unread,
Mar 25, 2013, 10:03:58 AM3/25/13
to bat...@googlegroups.com
Sigh.

The way to handle this with Jackson is to make the field Object. It
will be either a String or a Map<String, Object>. Alternatively I
suspect that if you make the field JsonNode then Jackson will do the
right thing.

If you want to encapsulate this, use JsonNode and then have two
different getter methods, one that returns the String version and one
that uses ObjectMapper to translate from JsonNode to your Location
structure (if appropriate).

Jeff
> --
> You received this message because you are subscribed to the Google Groups
> "BatchFB" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to batchfb+u...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Johannes Neubarth

unread,
Mar 27, 2013, 1:43:32 PM3/27/13
to bat...@googlegroups.com, je...@infohazard.org
Jeff, thanks a lot for your advice. I'm still a novice to Jackson.

For anybody interested, this is how I solved the issue. Those are the type definitions:
public static class Place {
        @JsonProperty("location")
        public JsonNode location;
}


public static class Location {
        @JsonProperty("latitude")
        public Double latitude;

        @JsonProperty("longitude")
        public Double longitude;
}


And then we can do:
Place place = post.place;
if (place != null) {
    // facebook is of type FacebookBatcher
    ObjectMapper mapper = facebook.getMapper();
    JsonNode locationNode = place.location;
    if (locationNode.isTextual()) {
        String locationName = locationNode.asText();
    } else {
        Location location = mapper.convertValue(locationNode, Location.class);
        if (location != null) {
            Double latitude = location.latitude;
            Double longitude = location.longitude;
        }
    }
}


Cheers, Hannes
Reply all
Reply to author
Forward
0 new messages