Jackson - Deserialize Array without property name - java

I have the following JSON response from shipcloud.io:
[
{
"name": "dhl",
"display_name": "Deutsche Post DHL",
"services": [
"standard",
"returns",
"one_day",
"one_day_early"
],
"package_types": [
"parcel",
"bulk"
]
},
{
"name": "dpag",
"display_name": "Deutsche Post",
"services": [
"standard"
],
"package_types": [
"letter",
"parcel_letter",
"books"
]
},
{
"name": "dpd",
"display_name": "DPD - Dynamic Parcel Distribution",
"services": [
"standard",
"returns",
"one_day",
"one_day_early"
],
"package_types": [
"parcel",
"parcel_letter"
]
}
]
How can I deserialize this JSON array with Jackson? Usually I use a simple POJO and define
the property name of the list / array (#JsonProperty("blub") e.g.). Problem is, there is no property name used here...
I tried it using an empty property name, but it didn't work.
I'm just getting this error message:
Can not deserialize instance of Response.CarriersResponse out of
START_ARRAY token

If you want to use jackson, this is the solution that works for me:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false);

You are deserializing multiple objects of the type, so you need to do it as a list, like this
// somewhere in an example TypeReferences class
public static final TypeReference<List<Response.CarriersResponse>> CARRIER_RESPONSES = new TypeReference<List<Response.CarriersResponse>>() {
};
// elsewhere where you're calling the mapper
List<Response.CarriersResponse> responses = mapper.readValue(text, TypeReferences.CARRIER_RESPONSES);
You could instantiate it in-place, but that's a design decision between performance vs total memory consumption.

Try to deserialize to Response.CarriersResponse[] class.
Response.CarriersResponse[] responses = mapper.readValue(text, Response.CarriersResponse[].class);

Related

Deserializing Jackson object where key is value inside larger object

I have a rather large JSON object (this is a subset) I'm trying to parse:
{
"items": [
{
"Name": "Wallet",
"tags": [
"wallet",
"cardholder"
],
"features": {
"material": {
"location": "in-house"
},
"stitching": {
"location": "in-house"
}
},
"color": null,
"store": {
"address": "123 Main Street"
}
}
],
"jItem": 0
}
I have Java POJO's for all JSON objects except for the features object, which contains objects where the key is a dynamic value. My current only-POJO's code does this:
...
itemsJson = doGet(url);
ObjectMapper objMapper = new ObjectMapper();
Items items = objMapper.readValue(itemsJson, Items.class);
...
This gives me a hierarchy of Java POJO's representing my data. The one hitch is features. How can I parse the features data, with the keys as values, within this larger object? I've looked at other SO posts:
Deserialize JSON in Jackson where key is a value
Deserializing jackson dynamic key value
Jackson JSON key as value in Java
but none of these solutions have 1. an object where the key is the value and 2. an object where the key is the value is contained within an object. I do have parsing just the features working using this "just features JSON":
{
"features": {
"material": {
"location": "in-house"
},
"stitching": {
"location": "in-house"
}
}
}
with this code:
...
JsonNode jsonNodeRecord = objectMapper.readTree(App.class.getResourceAsStream("/data.json"));
List<JsonNode> recordNodes = jsonNodeRecord.findValues("features");
...
which gives me JsonNode's. This isn't ideal because I don't have my features data in a POJO.
The Question:
It's not clear to me how to integrate parsing the JSON using POJO's for everything except for features, with either the JsonNode code above or a custom deserializer as in the #1 SO link above.

Jackson map JSON containing different items for same object

I've got the follwoing JSON structure with the corresponding DTOs in Java:
{
"kind": "object 1",
"selfLink": "some_link",
"items": [
{
"kind": "subkind 1",
"name": "server 1",
"anotherObject": {
"link": "some_link",
"isSubcollection": true,
"items": [
{
"att 1": "value",
"att2": "value",
"att3": "value"
},
{
"att5": "value" ,
"att6": "value" ,
"att7": "value" ,
"att8": "value"
}
]
}
}
]
}
Now I want to map this into corresponding DTOs using Jackson. Using the #JsonIgnoreUnknown annotation, this works fine. The problem is within the items array: How can I map different classes from the same JSON list in Jackson? Of course I could create a huge class containing both's attributes, but that would not be my way of choice.
I hope you can help me.

rest assured to match value from a root json array

Am new to rest assured
I have a json response like this
{
"queryPath": "/api/",
"nId": "f084f5ad24fcfaa9e9faea0",
"statusCode": 707
"statusMessage": "Success",
"results": {
"data": [
{
"id": "10248522500798",
"capabilities": [
"men",
"women"
],
"name": "errt2"
},
{
"id": "418143778",
"capabilities": [
"dog",
"cat"
],
"name": "Livin"
}
]
}
}
String type = "men"
Using rest assured i need to check the type value men with capabilities array values
[
"men",
"women"
]
and
"capabilities": [
"dog",
"cat"
]
If the type value `men` not contains in any of the capabilities i need to raise error..how it is possible?
i used following code .But it is not working.any other way??
body("results.data.capabilities", hasItems(type));
Am getting error
Expected: (a collection containing "men")
Actual: [[ men,women
], [dog, cat]]
The problem is that your jsonPath
results.data.capabilities
points to both "capabilities" arrays since they are nested at the same level of your JSON. If you can reliably expect the first "capabilities" array to contain "men" then you can specify the first "capabilities" in your jsonPath like so:
results.data.capabilities[0]

Error parsing the json representation Can not deserialize instance of out of START_ARRAY token

I'm trying to map a JSON string to a java object and keep getting this error:
Error parsing the json representation Can not deserialize instance of com.mypackage.MyType out of START_ARRAY token at [Source: java.io.StringReader#3d9b7aeb; line: 1, column: 1]
I'm pretty sure this is a JSON syntax problem but nothing I try works. This is the Java code (I'm omitting the Exception handling for simplicity):
ObjectMapper mapper = new ObjectMapper();
BackupResource backup = mapper.readValue(json.toString(), BackupResource.class);
Here is my JSON string:
{
"resources" : [ "resource1" , "resource2" ],
"files" : [ "file1" , "file2" ],
"htmls" : [ "html1" , "html2" ]
}
I tried adding [ and ] around this string, and several other options suggested around here but nothing works. Can anyone help with the correct syntax?
EDIT: the Java class I need to map the JSON to:
public class BackupResources {
private List resources;
private List files;
private List htmls;
public SystemBackupResources() {
}
// getters / setters....
}
EDIT 2: I had a mismatch between fields in the class and parts of the json. The java filed name was htmlFiles but the json was htmlfiles (no cap.) This is a string that works:
"{\"services\" : [ \"service1\" , \"service2\" ], \"oFiles\" : [ \"ofile1\" , \"ofile2\" ], \"htmlFiles\" : [ \"htmlfile1\" , \"htmlfile2\" ] }"
but this doesn't:
{
"services" : [ "service1" , "service2" ],
"oFiles" : [ "ofile1" , "ofile2" ],
"htmlFiles" : [ "htmlfile1" , "htmlfile2" ]
}
Anyone sees the difference?

How can I parse an unqualified JSON array using Jackson?

So, I am accessing a third-party API and it's giving me this JSON object, but I'm having a whale of a time trying to find an elegant way to parse the resources sub-object using Jackson.
I'm assuming I have to write a custom deserializer, though I'm wondering if there's another way...
{
"somekey": "somevalue",
"resources": [
"list",
[
{
"#type": "com.yada.Yada",
"resource": {
"#type": "ServiceObjectReference",
"id": "emp1234",
"displayName": "Bob Smith"
},
"type": "TYPE_PERSON",
"resourceType": 200
},
{
"#type": "com.yada.Yada",
"resource": {
"#type": "ServiceObjectReference",
"id": "emp1235",
"displayName": "Sue Smith"
},
"type": "TYPE_PERSON",
"resourceType": 200
}
]
]
}
Since the value of resources is an array with different object type, probably you don't want to use POJO for the mapping. Not sure about your implementation of custom deserializer, but you might want to use ObjectMapper#readTree method, than read the node value based on its type
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(your_json_input);
JsnoNode resourcesNode = rootNode.path("resources");
for (JsonNode resourceNode : resourcesNode ) {
if (resourceNode.isObject()) {
// the node is an object, you could do POJO mapping now or keep using path() method to go deeper
} else {
// simply get the String value
String list = resourceNode.getTextValue();
}
}
It looks like the producer of the json uses polymorphic type handling.
We can all agree that this is not something to use in a public api.
However, you could try to annotate your classes so that jackson can make use of this though.
The annotation #JsonTypeInfo would be your starting point
It would look something like this:
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true)
#JsonSubTypes({
#JsonSubTypes.Type(value = MyYada.class, name="com.yada.Yada")
})
public class MyYada
I did some more research and it looks like this is a "2-element JSON array". It can be parsed using JsonTypeInfo.As(WRAPPER_ARRAY)
http://jackson.codehaus.org/1.9.9/javadoc/org/codehaus/jackson/annotate/JsonTypeInfo.As.html#WRAPPER_ARRAY

Categories

Resources