Can't understand JsonMappingException - java

When running the following line:
Request<Map<String, Object>> requestMap = JsonUtils.fromJson(eventContext.getMessage().getPayloadAsString(), Request.class);
I got this Java exception:
Root Exception stack trace:
org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type, class ***.objectmodel.Request] from JSON floating-point number; no one-double/Double-arg constructor/factory method

It looks, for me, that you are trying to turn the String (JSON) into a Request, but you are not specifying which kind of Request (generic parameters) you are trying to parse.
I would try to extract that JSON into a Map like this:
Map<String, Object> actual = JsonUtil.fromJson(encoded, new TypeReference<Map<String, Object>>(){});
Once you are receiving a JSON and wants to deserialize it, I believe it have information and you must create a specific entity to map it, then it would be like this:
Map<String, YourEntity> actual = JsonUtil.fromJson(encoded, new TypeReference<Map<String, YourEntity>>(){});
More details about this solution you can find here.

I found the problem while debugging.
The JSON string was actually not a JSON (particulary only an ip address string "192.168.1.1". So it was not a deserialization mapping issue with the target class (as I supposed initially).
Moral of the fable: The exception is too complicated. A "Not a JSON string" would have been enough.

Related

Serialization and Deserialization of generic Map for Java and external use

I have a Map<String, Object> which I am using as a mapping for a JSON document, however want to create and maintain Java type information at the same time as retaining the structure of the document.
I'm attempting to use Jackson to create the document and it seems to work fine but I'm seeing something strange when attempting to deserialize it. A very simple serialization example:
final ObjectMapper mapper = new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.EXTERNAL_PROPERTY);
final Map<String, Object> map = Maps.newHashMap();
map.put("test", new Date());
final String ser = mapper.writeValueAsString(map);
final Map<String, Object> deser = mapper.readValue(ser, new TypeReference<HashMap<String, Object>>(){});
System.err.println(deser.get("test").getClass());
Gives the serialized form {"test":1410721662084,"#class":"java.util.Date"} which seems fine but when deserializing returns the type of "test" to be Long.
If I change the type serialization to use WRAPPER_ARRAY rather than EXTERNAL_PROPERTY then the type of "test" is correctly returned as Date, but doing this alters the structure of the JSON document so is not something I'm allowed to do. How do I retain the structure of the document as well as allow deserialization back to the correct types?
This is against Jackson 2.4.2.
Deserialization with maps is always tricky as maps don't preserve type information, which makes Jackson resort to #class and that not something you usually want. Instead, you can create a simple class:
public class TestClass {
private Date test;
//getters and setters omitted
}
This class has concrete structure and JSON will serialize it as
{ "test" : 1410721662084}
which is much cleaner and type-safe representation of your object. Then you just need to pass TestClass.class to readValue() method and your test attribute will be magically converted to proper type (Date)

How to get a List<JsonPath> from restassured JsonPath

I am using restassured framework, and inside it, it has JsonPath class.
JsonPath has a method signature of getList(String path, Class T);
I have attempt to do something like this:
List<JsonPath> myList = myJsonPathObject.getList("mypath", JsonPath.class);
And I get a runtime casting exception. So what would be the correct format in calling this.
I also attempted:
List<JsonPath> myList = myJsonPathObject.getList("mypath", new ArrayList<JsonPath>().getClass());
And that also failed. Actually that failed compilation.
JsonPath is used to extract values out of a JSON document. You cannot get a list of "JsonPath" out of JSON document.
I know this is an old threat, but someone commented and reminded me of this. I actually found an answer to this question.
What I had to do was cast it into a Map<String, Object> and while iterating through the objects, I have to cast the object into the appropriate class.
Map<String, Object> myMap = (Map<String, Object>) myJsonPathObject.get("mypath");
for (String key : myMap.getKeySet()) {
Map<String, Object> subMyMap = (Map<String, Object>) myMap.get(key);
}
So now I can continue to get additional mockup, json within a json.

JsonMappingException NOT getting thrown when it should

I have a class in Java that is generically typed. It is supposed to return an object of type T after receiving some json. I am using the following code to create the object:
ObjectMapper mapper = new ObjectMapper();
this.object = mapper.readValue(json, type);
This method throws a JsonMappingException, and should do so if the object isn't of the proper type. The problem I'm running into (when unit testing) is that if I pass in json of an incorrect type, as long as both objects are pojos no exception is being thrown. I am simply getting back an object of the correct type where all it's fields are null.
Why is the exception not getting thrown here? If I pass in some json with a bunch of fields that don't exist on the type of object it should be mapping to, shouldn't I get an exception from that?
You possibly have:
#JsonIgnoreProperties(ignoreUnknown = true)
set somewhere, so jackson doesn't complain about the mismatch.
How do you expect Jackson to know JSON does not represent expected type? JSON data does not have type, beyond just basic Object/Array/scalars structure. So as long as structure is compatible things work, and this is by design.

Jackson throws JsonMappingException on deserialize; demands single-String constructor?

Another question, but it relates to this one:
Deserializing JSON with Jackson - Why JsonMappingException "No suitable constructor"?
This time I am getting a different error, namely that the Jackson deserializer complains that I do not have a "single-String constructor/factory method" in my class ProtocolContainer.
However, if I add a single-String constructor, like this:
public ProtocolContainer(String json) {}
the exception does indeed disappear, but the ProtocolContainer that I expected to be there is all "empty", i.e. all its properties are in their initial state, and not populated according to the JSON-string.
Why is that?
I'm pretty sure you shouldn't need a single-String constructor, and if you do that you should not have to populate the properties in that constructor, right?
=)
Oh, so once again I found out the answer AFTER I posted this question (even though I tried a lot of things before posting).
What I did to solve this was to use the #JsonCreator annotation. I simply annotated my static Create method, like this:
#JsonCreator
public static ProtocolContainer Create(String jsonString)
{
ProtocolContainer pc = null;
try {
pc = mapper.readValue(jsonString, ProtocolContainer.class);
} catch (JsonParseException|JsonMappingException|IOException e) {
// handle
}
return pc;
}
And then problem solved.
The exception suggests that the JSON value you have is a String, something like:
{ "protocol" : "http" }
or perhaps "double-quoted JSON":
"\"{\"property\":\"value\"}\"
when trying to bind like:
ProtocolContainer p = mapper.readValue(json, ProtocolContainer.class);
in which case Jackson has no properties to map, just a String. And in that case it does indeed require either a custom deserializer, or a creator method. Creator methods are either single-string-argument constructors, or single-string argument static methods: the difference being that only constructors can be auto-detected (this is just a practical short-cut as there can only be one such constructor, but multiple static methods).
Your solution does indeed work, just thought I'd give some background as to what is happening.
Reading through it second time it seems more likely you have double-quoted stuff (JSON in JSON): another thing to consider is to get plain JSON, if possible. But maybe that's hard to do.
I had the same problem. For me, the solution was to switch from passing a String to the convertValue method, to an InputStream to the readValue method:
// Instead of this:
String jsonString = "..."
ProtocolContainer pc = mapper.convertValue(jsonString, ProtocolContainer.class);
// ... do this:
String jsonString = "..."
InputStream is = new StringInputStream(jsonString);
ProtocolContainer pc = mapper.readValue(is, ProtocolContainer.class);
It seems that you are sending to the server a string instead of an object.
Instead of sending the string to be parsed on the server side, you can do it easier just by sending JSON.parse(stringObject), and Jackson will deserialize it normally as expected.

Constructing POJO out of JSON string with dynamic fields using Gson

I'm consuming a web service in my application that will return a list of ID's associated with a name. An example would look like this:
{
"6502": "News",
"6503": "Sports",
"6505": "Opinion",
"6501": "Arts",
"6506": "The Statement"
}
How would I construct a POJO for Gson to deserialize to when all of the fields are dynamic?
How about deserializing into a map?
Gson gson = new Gson();
Type mapType = new TypeToken<Map<String, String>>() {}.getType();
String json = "{'6502':'News','6503':'Sports','6505':'Opinion','6501':'Arts','6506':'The Statement'}";
Map<String, String> map = gson.fromJson(json, mapType);
Using a map sounds reasonable for me (as Java is statically typed). Even if this could work (maybe using JavaCompiler) - accessing the object would not probably be much different from accessing a map.
I don't know Gson that well but I suspect that's not possible. You'd have to know which fields are possible beforehand, although the fields might not be in the Json and thus be null.
You might be able to create classes at runtime by parsing the Json string, but I don't know whether that would be worth the hassle.
If everything is dynamic your best bet would be to deserialize the Json string to maps of strings or arrays etc. like other Json libraries do (I don't know whether Gson can do this as well, but the classes you need are commonly called JSONObject and JSONArray).
So your Json string above would then result in a Map<String, String>.

Categories