I need to deserialize the following:
{
"name": "library",
"contains": [
{
"name: "office",
"contains": []
},
{
"name": "Home",
"contains":[{
"name": "Shelf",
"contains" : []
}]
}]
}
My class looks like this:
public class Container
{
String containerName;
}
Public class Contains extends Container {
#SerializedName("contains")
#Expose
private List<Container> contains;
}
How is it that when I run my code, I am hoping to get a contains object to run my methods it won't get me them. But I get a container object and can't run my methods from within my Contains class.
You don't need inheritance here. Just use Gson.fromJson().
Object class
public class Container {
#SerializedName("name")
#Expose
private String name;
#SerializedName("contains")
#Expose
private List<Container> contains;
public Container(String name) {
this.name = name;
contains = new ArrayList<Container>();
}
public void setName(String name) {
this.name = name;
}
public void add(Container c) {
this.contains.add(c);
}
public void setContainerList(List<Container> contains) {
this.contains = contains;
}
public String getName() {
return name;
}
public List<Container> getContainerList() {
return this.contains;
}
}
Code
public static void main(String[] args) {
Container lib = new Container("library");
Container office = new Container("office");
Container home = new Container("Home");
Container shelf = new Container("Shelf");
home.add(shelf);
lib.add(office);
lib.add(home);
Gson gson = new Gson();
// Serialize
String json = gson.toJson(lib);
// Deserialize
Container container = gson.fromJson(json, Container.class);
System.out.println(container.getName());
for (Container c : container.getContainerList()) {
System.out.println("-- " + c.getName());
}
}
Output
library
-- office
-- Home
Related
I have a basic SpringBoot 2.1.5.RELEASE app. Using Spring Initializer, JPA, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file with some RestControllers.
In 1 of the controller this is the body I send:
{
"depositHotel": "xxx",
"destinationHotel": "aaa",
"depositHotelAmount": "0.2",
"destinationHotelAmount": "4",
"destinationAddress": [{
"address": "asdf",
"tag": ""
}],
"refundAddress": [{
"address": "pio",
"tag": ""
}]
}
so I create this class to use it as a RequestBody:
public class HotelswitchHotelOrderRequestBody {
public static class Builder {
private String depositHotel;
private String destinationHotel;
private Float depositHotelAmount;
private Float destinationHotelAmount;
private JSONObject destinationAddress;
private JSONObject refundAddress;
public Builder(String depositHotel, String destinationHotel) {
this.depositHotel = depositHotel;
this.destinationHotel = destinationHotel;
}
public Builder withDepositHotelAmount (Float depositHotelAmount) {
this.depositHotelAmount = depositHotelAmount;
return this;
}
public Builder withDestinationHotelAmount (Float destinationHotelAmount) {
this.destinationHotelAmount = destinationHotelAmount;
return this;
}
public Builder toDestinationAddress (JSONObject destinationAddress) {
this.destinationAddress = destinationAddress;
return this;
}
public Builder toRefundAddress (JSONObject refundAddress) {
this.refundAddress = refundAddress;
return this;
}
public HotelswitchHotelOrderRequestBody build(){
HotelswitchHotelOrderRequestBody order = new HotelswitchHotelOrderRequestBody();
order.depositHotel = this.depositHotel;
order.depositHotelAmount = this.depositHotelAmount;
order.destinationAddress = this.destinationAddress;
order.destinationHotel = this.destinationHotel;
order.destinationHotelAmount = this.destinationHotelAmount;
order.refundAddress = this.refundAddress;
return order;
}
}
private String depositHotel;
private String destinationHotel;
private Float depositHotelAmount;
private Float destinationHotelAmount;
private JSONObject destinationAddress;
private JSONObject refundAddress;
private HotelswitchHotelOrderRequestBody () {
//Constructor is now private.
}
public String getDepositHotel() {
return depositHotel;
}
public void setDepositHotel(String depositHotel) {
this.depositHotel = depositHotel;
}
public String getDestinationHotel() {
return destinationHotel;
}
public void setDestinationHotel(String destinationHotel) {
this.destinationHotel = destinationHotel;
}
public Float getDepositHotelAmount() {
return depositHotelAmount;
}
public void setDepositHotelAmount(Float depositHotelAmount) {
this.depositHotelAmount = depositHotelAmount;
}
public Float getDestinationHotelAmount() {
return destinationHotelAmount;
}
public void setDestinationHotelAmount(Float destinationHotelAmount) {
this.destinationHotelAmount = destinationHotelAmount;
}
public JSONObject getDestinationAddress() {
return destinationAddress;
}
public void setDestinationAddress(JSONObject destinationAddress) {
this.destinationAddress = destinationAddress;
}
public JSONObject getRefundAddress() {
return refundAddress;
}
public void setRefundAddress(JSONObject refundAddress) {
this.refundAddress = refundAddress;
}
}
But I have this error when receiving the object:
JSON parse error: out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `org.json.JSONObject` out of START_ARRAY token
JSONObject's representation in actual JSON is a hash i.e. {...}. In your json data you're providing an array of hashes [{...}] which is not the same. Judging from your domain I don't think it has to be multiple values, so you can just omit [] in your payload and if it does then the fields in your Java class can be defined as JSONArray.
However, I think you should go with defining an Address class and either using
private Address destinationAddress;
private Address refundAddress;
or if it indeed does have to be an object array
private List<Address> destinationAddresses;
private List<Address> refundAddresses;
I had a similar usecase , where I could not define the json to a POJO. Using com.fasterxml.jackson.databind.JsonNode instead of the JSONObject worked.
My Use case is I have a json file but I have to share only few of them to client.
Ex: Consider the source json file as shown below.
{
"name": "XYZ",
"age": 24,
"education": {
"college": "ppppp",
"study": "b.tech",
"grade": 6.8
},
"friends": ["kkkk",
"bbbbbbbbbbb",
"jjjjjj"],
"dob":"01-08-1990"
}
For client 1 I have to share below output
{
"personalInfo": {
"name": "XYZ",
"age": 24,
"friendsNames": ["kkkk","bbbbbbbbbbb","jjjjjj"]
},
"educationalInfo": {
"college": "ppppp",
"study": "b.tech",
"grade": 6.8
}
}
For client 2 I have to share below output
{
"personalInformation": {
"nameOfEmployee": "XYZ",
"ageOfEmployee": 24
},
"educationalInformation": {
"college": "ppppp",
"study": "b.tech"
}
}
And for other clients also the use case is same, I have to skip some keys and give different names to the keys. How to dynamically do this by some kind of configuration. I used jsonPath to achieve this but removing few keys from json object is difficult. Any suggestions can be appreciated.
Use a JSON Path library, like JayWay. With that, templates to transform your exapmle would be:
Client 1
{
"personalInfo": {
"name": "$.name",
"age": "$.age",
"friendsNames": "$.friends"
},
"educationalInfo": "$.education"
}
Client 2
{
"personalInformation": {
"nameOfEmployee": "$.name",
"ageOfEmployee": "$.age"
},
"educationalInformation": {
"college": "$.education.college",
"study": "$.education.study"
}
}
What you need to implement is the template traversal. It's about 20 lines of code; or 40 if you also need to transform list elements, like:
{
"friends": [ "$.friends[?(# =~ /.{5,}/)]", {
"name": "#",
"since": "$.dob"
} ]
}
which would result into:
{
"friends": [ {
"name": "bbbbbbbbbbb",
"since": "01-08-1990"
}, {
"name": "jjjjjj",
"since": "01-08-1990"
} ]
}
You can use Jackson to serialize and deserialize json. I suggest you to create seperate classes which represents your client data.
I show you an example of how you can deserialize your data and map it to your client json.
You can generate corresponding classes for client 2 with getting some help from http://www.jsonschema2pojo.org/ for mapping json to pojo.
Here is the code :
public class Main {
public static void main(String[] args) throws ParseException, ParserConfigurationException, IOException, SAXException {
ObjectMapper mapper = new ObjectMapper();
Root root = mapper.readValue(new File("test.json"), Root.class);
Client1 c1 = new Client1();
PersonalInfo personalInfo1 = new PersonalInfo();
personalInfo1.setAge(root.getAge());
personalInfo1.setFriendsNames(root.getFriends());
personalInfo1.setName(root.getName());
EducationalInfo educationalInfo1 = new EducationalInfo();
educationalInfo1.setCollege(root.getEducation().getCollege());
educationalInfo1.setGrade(root.getEducation().getGrade());
educationalInfo1.setStudy(root.getEducation().getStudy());
c1.setPersonalInfo(personalInfo1);
c1.setEducationalInfo(educationalInfo1);
mapper.writeValue(new File("client1.json"), c1);
}
}
Inside test.json file :
{
"name": "XYZ",
"age": 24,
"education": {
"college": "ppppp",
"study": "b.tech",
"grade": 6.8
},
"friends": [
"kkkk",
"bbbbbbbbbbb",
"jjjjjj"
],
"dob": "01-08-1990"
}
Inside client1.json file :
{
"personalInfo": {
"name": "XYZ",
"age": 24,
"friendsNames": [
"kkkk",
"bbbbbbbbbbb",
"jjjjjj"
]
},
"educationalInfo": {
"college": "ppppp",
"study": "b.tech",
"grade": 6.8
}
}
Here is the classes which represents your json data:
class Education {
private String college;
private String study;
private float grade;
public String getCollege() {
return college;
}
public void setCollege(String college) {
this.college = college;
}
public String getStudy() {
return study;
}
public void setStudy(String study) {
this.study = study;
}
public float getGrade() {
return grade;
}
public void setGrade(float grade) {
this.grade = grade;
}
}
// root of your base json data
class Root {
private String name;
private int age;
private Education education;
private List<String> friends;
private String dob;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Education getEducation() {
return education;
}
public void setEducation(Education education) {
this.education = education;
}
public List<String> getFriends() {
return friends;
}
public void setFriends(List<String> friends) {
this.friends = friends;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
}
class EducationalInfo {
private String college;
private String study;
private float grade;
public String getCollege() {
return college;
}
public void setCollege(String college) {
this.college = college;
}
public String getStudy() {
return study;
}
public void setStudy(String study) {
this.study = study;
}
public float getGrade() {
return grade;
}
public void setGrade(float grade) {
this.grade = grade;
}
}
// class which represents client 1 json data
class Client1 {
private PersonalInfo personalInfo;
private EducationalInfo educationalInfo;
public PersonalInfo getPersonalInfo() {
return personalInfo;
}
public void setPersonalInfo(PersonalInfo personalInfo) {
this.personalInfo = personalInfo;
}
public EducationalInfo getEducationalInfo() {
return educationalInfo;
}
public void setEducationalInfo(EducationalInfo educationalInfo) {
this.educationalInfo = educationalInfo;
}
}
class PersonalInfo {
private String name;
private int age;
private List<String> friendsNames = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<String> getFriendsNames() {
return friendsNames;
}
public void setFriendsNames(List<String> friendsNames) {
this.friendsNames = friendsNames;
}
}
What about converting it to XML then create some XSLT? it might be much readable and cleaner.
I push full worked example in java into GIT with libs (lombok and jackson)
Template json mapped to object and object to json with different clients.
Your job is to output multilevel JSON data as multiple JSON formats. JSONPath can do this but the process is a hassle.
A simple alternative is to use SPL. SPL is a Java open-source package. You just need three lines of code to get the job done:
enter image description here
SPL offers JDBC driver to be invoked by Java. Just store the above SPL script as jsonparse.splx and invoke it in a Java application as you call a stored procedure:
…
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
st = con.prepareCall("call jsonparse()");
st.execute();
…
Java doesn't have great templating built in.
But if you want to do a quick an dirty JSON template where you can replace a few values -- especially without all that ugly quote escaping:
{"key":"value"}
You can use single quotes and string replace:
{'key':'VALUE'}.replace("'", """).replace("VALUE", 42)
A few caveats:
This will break if any existing keys or values have single quotes (like O'malley).
It won't replace strings with numbers, boolean, or null
It can't -- by itself -- insert nested arrays or objects (e.g. [] {}) other than as strings.
But with a little bit of of extra work, you can accomplish the 80/20 rule. After that point you'd probably want to look into parsing or generating -- but by then you're not looking for a quick template.
I need to send a json to a web address where this json will be consumed, basically I have a list of Dto's that I need to turn into a Json (with jackson).
Some information must be passed in the header:
timestamp= time, key= blablabla, accesskey= bla bla bla
As I have no experience with spring, i need to know how to do the HTTP request using Spring boot
(is it a post?)
Here's what I've implemented so far:
Student Dto Class
public class StudentDto {
private String name;
private String RM;
private String RG;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRM() {
return RM;
}
public void setRM(String RM) {
this.RM = RM;
}
public String getRG() {
return RG;
}
public void setRG(String RG) {
this.RG = RG;
}
}
Turning my list of students into json
public String convertToJson(List obj) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
String jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
return jsonInString;
}
}
And this is the format json has to leave
{
"table": "student",
"rows":
[
{
"PersonID": 1,
"name": "Name",
"RM": "56656565",
"RG": "8787845-7",
},
{
"PersonID": 2,
"name": "Name",
"RM": "56656565",
"RG": "8787845-7"
}
]
}
below is and example of how to use rest template. You'll want to create a class for the request that has String table; and List<StudentDto> rows; as members
private static void createEmployee()
{
final String uri = "http://localhost:8080/springrestexample/employees";
MultiValueMap<String> headers = new MultiValueMap<>();
//set headers
HttpEntity<EmployeeVO> newEmployee = new HttpEntity<>(new EmployeeVO(-1, "Adam", "Gilly", "test#email.com"),headers);
RestTemplate restTemplate = new RestTemplate();
EmployeeVO result = restTemplate.postForObject( uri, newEmployee, EmployeeVO.class);
System.out.println(result);
}
*edit added headers
*edid look here for json formatting
you will also need to have the id field added to your object
I have a question how to map JSON Objects with same key to different objects.
If I write 2 classes with the specific fields I get an error because the data element is contained twice.
How can I map the resource A to class A and the resource B to class B?
{
"ETag":"oiojojojojoj==",
"elements":[
{
"resource":"A",
"ETag":null,
"data":[
{
"anotherfield":"text",
"id":1,
"name":"GB"
}
]
},
{
"resource":"B",
"ETag":"dmVuZG9yOzIwMTctMDUtMDlUMTQ6MzE6NDNa",
"data":[
{
"field":"read",
"id":1
}
]
}
]
}
The classes could look like this:
public class Element {
#JsonProperty("resource")
public String resource = null;
#JsonProperty("ETag")
public Object eTag = null;
#JsonProperty("data")
public List<A> dataInA = null;
#JsonProperty("data")
public List<B> dataInB = null;
}
public class Example {
#JsonProperty("ETag")
public String eTag;
#JsonProperty("elements")
public List<Element> elements = null;
}
Class A
public class A {
#JsonProperty("anotherfield")
public String anotherfield;
#JsonProperty("id")
public Integer id;
#JsonProperty("name")
public String name;
}
Class B
public class B {
#JsonProperty("field")
public String field;
#JsonProperty("id")
public Integer id;
}
Thanks a lot!
EDIT:
When I switch the JSON elements to dataA and dataB It works.
{
"ETag":"oiojojojojoj==",
"elements":[
{
"resource":"A",
"ETag":null,
"dataA":[
{
"anotherfield":"text",
"id":1,
"name":"GB"
}
]
},
{
"resource":"B",
"ETag":"dmVuZG9yOzIwMTctMDUtMDlUMTQ6MzE6NDNa",
"dataB":[
{
"field":"read",
"id":1
}
]
}
]
}
Element class:
public class Element {
#JsonProperty("resource")
public String resource;
#JsonProperty("ETag")
public Object eTag;
#JsonProperty("dataA")
public List<A> dataInA;
#JsonProperty("dataB")
public List<B> dataInB;
}
I have defined JSON response which I want to deserialize into Java Objects. I managed to do it "manually" with the Tree Model but if possible I would like to use Data Binding instead. The problem is that I need some custom logic for some parts.
The JSON looks like this:
{
"resourcedescriptions": [
{
"path": "somePath",
"tag_pagetype": "default",
"tag_bookingcenter": [
"bc_ch",
"bc_de"
],
"resources": [
{
"path": "somePathDe.html",
"lang": "de",
"lastmodified": 1399020442914,
"mimetype": "text/html"
},
{
"path": "somePathEn.html",
"lang": "en",
"lastmodified": 1399907224208,
"mimetype": "text/html"
}
],
"lastmodified": 1399907224208
},
{
"path": "someOtherPath",
"tag_pagetype": "special",
"tag_bookingcenter": [
"bc_ch"
],
"resources": [
{
"path": "someOtherPathDe.html",
"lang": "de",
"lastmodified": 1399020442914,
"mimetype": "text/html"
},
{
"path": "someOtherPathEn.html",
"lang": "en",
"lastmodified": 1399907224208,
"mimetype": "text/html"
}
],
"lastmodified": 1399907224208
}
]
}
My Java Classes would be:
public class ResourceDescription {
private String path;
private LocalDateTime lastModified;
private String chartConfig;
private final List<Tag> tags = new ArrayList<Tag>();
private final List<Resource> resources = new ArrayList<Resource>();
}
public class Resource {
private String lang;
private String path;
private String mimeType;
private LocalDateTime lastModified;
}
public class Tag {
private String namespace;
private String name;
}
First question which I still don't fully understand even with reading many posts here. How do I deserialize this array of Resources from the JSON into my List of the ResourceDescription?
Second and most complex question. The JSON properties prefixed with "tag_" need to be transformed into the Tag class, whereas the the property name represents the namespace and the value (single or array) represent the name. So if the pattern is "namespace:name", the first ResourceDescription would have the following tags:
tag_pagetype:default
tag_bookingcenter:bc_ch
tag_bookingcenter:bc_de
Third the "lastmodified" should be transformed into DateTime from Joda-Time.
Is this even possible with data binding or should I stick to the Tree Model?
How do I deserialize this array of Resources from the JSON into my
List of the ResourceDescription?
You have to create additional root class which contains resourcedescriptions property. For example:
class Root {
private List<ResourceDescription> resourcedescriptions;
public List<ResourceDescription> getResourcedescriptions() {
return resourcedescriptions;
}
public void setResourcedescriptions(List<ResourceDescription> resourcedescriptions) {
this.resourcedescriptions = resourcedescriptions;
}
#Override
public String toString() {
return String.valueOf(resourcedescriptions);
}
}
The JSON properties prefixed with "tag_" need to be transformed into
the Tag class, whereas the the property name represents the namespace
and the value (single or array) represent the name.
You can handle this case using #JsonAnySetter annotation. You have to add new method to ResourceDescription class which could look like this:
#JsonAnySetter
public void setAnyValues(String propertyName, Object value) {
if (propertyName.startsWith("tag_")) {
if (value instanceof String) {
tags.add(new Tag(propertyName, value.toString()));
} else if (value instanceof List) {
List<?> values = (List<?>) value;
for (Object v : values) {
tags.add(new Tag(propertyName, v.toString()));
}
}
// throw exception?
} else {
// handle another unknown properties
}
}
Third the "lastmodified" should be transformed into DateTime from
Joda-Time.
You can handle JodaTime types by adding jackson-datatype-joda library. When you add it you can register JodaModule module.
mapper.registerModule(new JodaModule());
Additional problem that your JSON contain properties written using lowercase, but your POJO properties are written using camel-case. You can change JSON or POJO or use #JsonProperty("property-name-from-JSON") annotation or implement your own naming strategy. For example:
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.PropertyNamingStrategyBase() {
#Override
public String translate(String propertyName) {
return propertyName.toLowerCase();
}
});
Full Java example how to you can deserialize your JSON:
import java.util.ArrayList;
import java.util.List;
import org.joda.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.datatype.joda.JodaModule;
public class JacksonProgram {
public static void main(String[] args) throws Exception {
String json = "{ ... }";
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.PropertyNamingStrategyBase() {
#Override
public String translate(String propertyName) {
return propertyName.toLowerCase();
}
});
System.out.println(mapper.readValue(json, Root.class));
}
}
class Root {
private List<ResourceDescription> resourcedescriptions;
public List<ResourceDescription> getResourcedescriptions() {
return resourcedescriptions;
}
public void setResourcedescriptions(List<ResourceDescription> resourcedescriptions) {
this.resourcedescriptions = resourcedescriptions;
}
#Override
public String toString() {
return String.valueOf(resourcedescriptions);
}
}
class ResourceDescription {
private String path;
private LocalDateTime lastModified;
private String chartConfig;
private final List<Tag> tags = new ArrayList<Tag>();
private final List<Resource> resources = new ArrayList<Resource>();
#JsonAnySetter
public void setAnyValues(String propertyName, Object value) {
if (propertyName.startsWith("tag_")) {
if (value instanceof String) {
tags.add(new Tag(propertyName, value.toString()));
} else if (value instanceof List) {
List<?> values = (List<?>) value;
for (Object v : values) {
tags.add(new Tag(propertyName, v.toString()));
}
}
// throw exception?
} else {
// handle another unknown properties
}
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public LocalDateTime getLastModified() {
return lastModified;
}
public void setLastModified(LocalDateTime lastModified) {
this.lastModified = lastModified;
}
public String getChartConfig() {
return chartConfig;
}
public void setChartConfig(String chartConfig) {
this.chartConfig = chartConfig;
}
public List<Tag> getTags() {
return tags;
}
public List<Resource> getResources() {
return resources;
}
#Override
public String toString() {
return "ResourceDescription [path=" + path + ", lastModified=" + lastModified
+ ", chartConfig=" + chartConfig + ", tags=" + tags + ", resources=" + resources
+ "]";
}
}
class Resource {
private String lang;
private String path;
private String mimeType;
private LocalDateTime lastModified;
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getMimeType() {
return mimeType;
}
public void setMimeType(String mimeType) {
this.mimeType = mimeType;
}
public LocalDateTime getLastModified() {
return lastModified;
}
public void setLastModified(LocalDateTime lastModified) {
this.lastModified = lastModified;
}
#Override
public String toString() {
return "Resource [lang=" + lang + ", path=" + path + ", mimeType=" + mimeType
+ ", lastModified=" + lastModified + "]";
}
}
class Tag {
private String namespace;
private String name;
public Tag() {
}
public Tag(String namespace, String name) {
this.namespace = namespace;
this.name = name;
}
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "Tag [namespace=" + namespace + ", name=" + name + "]";
}
}
Above program prints:
[ResourceDescription [path=somePath, lastModified=2014-05-12T17:07:04.208, chartConfig=null, tags=[Tag [namespace=tag_pagetype, name=default], Tag [namespace=tag_bookingcenter, name=bc_ch], Tag [namespace=tag_bookingcenter, name=bc_de]], resources=[Resource [lang=de, path=somePathDe.html, mimeType=text/html, lastModified=2014-05-02T10:47:22.914], Resource [lang=en, path=somePathEn.html, mimeType=text/html, lastModified=2014-05-12T17:07:04.208]]], ResourceDescription [path=someOtherPath, lastModified=2014-05-12T17:07:04.208, chartConfig=null, tags=[Tag [namespace=tag_pagetype, name=special], Tag [namespace=tag_bookingcenter, name=bc_ch]], resources=[Resource [lang=de, path=someOtherPathDe.html, mimeType=text/html, lastModified=2014-05-02T10:47:22.914], Resource [lang=en, path=someOtherPathEn.html, mimeType=text/html, lastModified=2014-05-12T17:07:04.208]]]]
You will need to create a custom deserializer for ResourceDescription in order to accomplish what you need to do. The syntax for specifying a custom deserializer for ResourceDescription will look like this:
#JsonDeserialize(using=ResourceDescriptionDeserializer.class)
public class ResourceDescription { ... }
This deserializer will have to iterate through each of the keys for each resource description to see if it begins with "tag_", strip off the prefix and use the remaining for the namespace and populate the name/value for the Tag before adding it to the array of the ResourceDescription being created.
For all other attributes/types I think you can just defer to the default deserialization and set those attributes on their respective fields.
Then, to deserialize the list of ResourceDescriptions you can specify a TypeReference to avoid writing a custom deserializer for ResourceDescriptions. The code will look something like this:
Map<String, List<ResourceDescription>> resultMap =
objectMapper.readValue(JSON, new TypeReference<Map<String, List<ResourceDescription>>>() {});
List<ResourceDescription> descriptions = resultMap.get("resourcedescriptions");
Here's an article that doesn't quite pair with what you're doing but I think will help with the general idea:
Using Jackson to deserialize array nested within array in JSON object