Mapping an array of JSon string into Pojo - java

Everytime I map an array of JSON object into POJOs, I always get the last object.
The JSON is an array of objects, and I have a POJO associate with each object of JSON. But when I mapped into an array of POJO, I always get 1 object.
Here is the JSON :
[ {
"event" : {
"Id" : "123456789",
"Name" : "An event1 name"
},
"branch" : {
"Id" : "112233445566",
"Name" : "A branch1 name",
},
"user" : {
"Id" : "9988776655",
"FirstName" : "John",
"LastName" : "Doe",
},
"event" : {
"Id" : "abcdef",
"Name" : "An event2 name"
},
"branch" : {
"Id" : "885522",
"Name" : "A branch2 name",
},
"user" : {
"Id" : "996633",
"FirstName" : "Jane",
"LastName" : "Doe",
}
} ]
The POJOs:
public class RdV {
private Event event;
private Branch branch;
private User user;
public Event getEvent() {
return event;
}
public void setEvent(Event event) {
this.event = event;
}
public Branch getBranch() {
return branch;
}
public void setBranch(Branch branch) {
this.branch= branch;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#Override
public String toString() {
return "RdV [\n"
+ event + "\n"
+ branch + "\n"
+ user + "\n"
+ "]";
}
}
public class Event {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name= name;
}
}
The other POJOS, Branch and User are similar to Event.
And when I use the following :
List<RdV> rdv = Arrays.asList(objectMapper.readValue(jsonString, RdV[].class));
all I got is just the last object ( the size of list is 1, instead of 2 ):
==> RdV [
Event {
id="abcdef",
name="An event2 name"
}
Branch {
id="885522",
name="A branch2 name"
}
User {
id="996633",
lastName="Doe",
firstName="Jane"
}
]
Any idea what went wrong the code ?
Thanks.

your JSON doesn't have two separate objects - just one with double properties of Branch, Event and User, you should change it to
[
{
"event": {
"Id": "123456789",
"Name": "An event1 name"
},
"branch": {
"Id": "112233445566",
"Name": "A branch1 name"
},
"user": {
"Id": "9988776655",
"FirstName": "John",
"LastName": "Doe"
}
},
{
"event": {
"Id": "abcdef",
"Name": "An event2 name"
},
"branch": {
"Id": "885522",
"Name": "A branch2 name"
},
"user": {
"Id": "996633",
"FirstName": "Jane",
"LastName": "Doe"
}
}
]

Related

Json deserialization with key value mapped object

I'm trying to deserialize a json string to Java object. Here is my json string.
{
"header": {
"transactionId": "12345",
"application": "testApp"
},
"items": {
"item": [
{
"attributes": {
"attribute": [
{
"key": "accountType",
"value": "TYPE1"
},
{
"key": "accountId",
"value": "123"
}
]
}
},
{
"attributes": {
"attribute": [
{
"key": "userType",
"value": "TYPE2"
},
{
"key": "userId",
"value": "321"
}
]
}
}
]
}
}
And I want to deserialize this json to Java classes that shown as below.
public class Response {
private Header header;
private List<Object> items;
//getters and setters
}
public class Header {
private String transactionId;
private String application;
//getters and setters
}
public class Account {
private String accountType;
private String accountId;
//getters and setters
}
public class User {
private String userType;
private String userId;
//getters and setters
}
How can I deserialize by using jackson or objectmapper etc.? The main problem is the field names are in the attribute object and the value of 'key' field. Is it possible to find the right field on Java object by using value of the 'key' field and to set the right value with the value of the 'value' field?
One possible solution is to transform the JSON structure before converting to POJO.
https://github.com/octomix/josson
Josson josson = Josson.fromJsonString(yourJsonString);
JsonNode node = josson.getNode(
"map(header," +
" items: items.item#" +
" .attributes.attribute" +
" .map(key::value)" +
" .mergeObjects()" +
" )");
System.out.println(node.toPrettyString());
Output
{
"header" : {
"transactionId" : "12345",
"application" : "testApp"
},
"items" : [ {
"accountType" : "TYPE1",
"accountId" : "123"
}, {
"userType" : "TYPE2",
"userId" : "321"
} ]
}

Issue with a Json schema validation

I'm running into an issue with a Json schema validation.
I have a Java class like this
package com.ebc.jackson.exampe.data;
public class FormElement {
private String fieldName;
private String fieldType;
private Object value;
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public String getFieldType() {
return fieldType;
}
public void setFieldType(String fieldType) {
this.fieldType = fieldType;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
I'm using below code to generate the schema:
JsonSchemaGenerator generator =
new JsonSchemaGenerator(objectMapper);
JsonNode schema = generator.generateJsonSchema(FormElement.class);
String strSchema = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
this code generates below schema
{
"$schema" : "http://json-schema.org/draft-04/schema#",
"title" : "Form Element",
"type" : "object",
"additionalProperties" : false,
"properties" : {
"fieldName" : {
"type" : "string"
},
"fieldType" : {
"type" : "string"
},
"value" : {
"$ref" : "#/definitions/Object"
}
},
"definitions" : {
"Object" : {
"type" : "object",
"additionalProperties" : false,
"properties" : { }
}
}
}
In the request, I could receive a Json Object like
{
"fieldName": "user-name",
"fieldType": "textInput",
"value": "Alex"
}
When I try to validate this object against the Json schema, "value" attribute is not valid, it is expecting a "key: value" pair but, a string is found.
In the Java class the value attribute is Object because it could be a String, Integer, Boolean, etc.
My question is, how can I generate a schema to support different data types for "value" attribute?
You can use the anyOf property of schema :
Try the below one :
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Form Element",
"type": "object",
"additionalProperties": false,
"properties": {
"fieldName": {
"type": "string"
},
"fieldType": {
"type": "string"
},
"value": {
"$ref": "#/definitions/Object"
}
},
"definitions": {
"Object": {
"format": "",
"anyOf": [
{
"type": "object"
},
{
"type": "string"
},
{
"type": "number"
},
{
"type": "integer"
},
{
"type": "boolean",
"x-enumFlags": true
},
{
"type": "null"
}
],
"additionalProperties": false,
"properties": {}
}
}
}
Or you could try the pipe separator in type.In the schema you provided just change the value of type to "type": "string|object|integer|number". This notation didn't work for me in swagger but you can check if it works for you.

Unable to access profilePicture JSON parameter in LinkedIn profile response (Java)

I am trying to retrieve the profilePicture parameter in the LinkedIn liteProfile response. However, for some reason, they return two json objects with the same parameter name (Who even built this API?!).
Response:
{
"firstName": {
"localized": {
"en_US": "Damien"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
"lastName": {
"localized": {
"en_US": "Roger"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
"profilePicture": {
"displayImage": "urn:li:digitalmediaAsset:C5103AQEGbbhK9i7Qhw",
"displayImage~": {
"paging": {
"count": 10,
"start": 0,
"links": []
},
"elements": [
{
"identifiers": [
{
"identifier": "https://media.licdn.com/dms/image/C5103AQEGbbhK9i7Qhw/profile-displayphoto-shrink_200_200.....",
....
}
}
]
}
}
}
As you may have noticed, in profilePicture, there's two params called displayImage. One with a ~. How do I access this from a java pojo class?
My class looks like this:
public class LinkedInProfileResponse {
public FirstName firstName;
public LastName lastName;
public ProfilePicture profilePicture;
public String id;
public class ProfilePicture {
public String displayImage;
public DisplayImage displayImage;
}
}
The #SerializedName annotation can be used on a field in your POJO to specify the name of the JSON attribute to be mapped to the Java field.
So in your case:
...
#SerializedName("displayImage~)
public DisplayImage displayImage;
...

Aggregation lookup not working in spring

I am running the following aggregation lookup query in spring but it doesn't seems to output the same result as one i run in mongo shell. I am guessing mongo shell knows that from:"testModel" collection exists but how do spring know "testModel" exists as we are only pass strings in Aggregation.lookup("testModel"). I can run all other stages fine for example match or project..
// code running in Mongo Shell
db.demoModel.aggregate([{
$lookup:
{
from: "testModel",
localField: "_id",
foreignField: "makeId",
as: "cool"
}
}]
)
// code from spring
public List<DemoModel> getSomeAutos() throws Exception {
LookupOperation lookupStage = Aggregation.lookup(
"testModel",
"_id",
"makeId",
"cool"
);
Aggregation aggregation = Aggregation.newAggregation(lookupStage);
List<DemoModel> demomode = mongoTemplate.aggregate(aggregation, "demoModel", DemoModel.class).getMappedResults();
return demomode;
}
// DemoModel.class
public class DemoModel {
#Id
private String id;
private String value;
private String label;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}
//Mongo demoModel Collection
{
"_id" : ObjectId("5a8ee0d815dc17aa32f90f4b"),
"value" : "Mitsubishi",
"label" : "Mitsubishi"
}
{
"_id" : ObjectId("5a8ee0d815dc17aa32f90f4c"),
"value" : "BMW",
"label" : "BMW"
}
// Mongo testModel Collection
{
"_id" : ObjectId("5a8ee393b80c346266f25aba"),
"make" : "Mitsubishi",
"label" : "3000GT",
"value" : "3000GT",
"makeId" : ObjectId("5a8ee0d815dc17aa32f90f4b")
}
{
"_id" : ObjectId("5a8ee393b80c346266f25af8"),
"make" : "BMW",
"label" : "Alpina A2",
"value" : "Alpina A2",
"makeId" : ObjectId("5a8ee0d815dc17aa32f90f4c")
}
// Response i am getting
[
{
"id": "5a8ee0d815dc17aa32f90f4b",
"value": "Mitsubishi",
"label": "Mitsubishi"
},
{
"id": "5a8ee0d815dc17aa32f90f4c",
"value": "BMW",
"label": "BMW"
}
]
// expected response in this format
{
"_id" : ObjectId("5a8ee0d815dc17aa32f90f4b"),
"value" : "Mitsubishi",
"label" : "Mitsubishi",
"cool" : [
{
"_id" : ObjectId("5a8ee393b80c346266f25aba"),
"make" : "Mitsubishi",
"label" : "3000GT",
"value" : "3000GT",
"makeId" : ObjectId("5a8ee0d815dc17aa32f90f4b")
}]
}

Creating POJOs to match a JSON structure

I have devised a JSON structure to represent a table with header columns plus table rows that looks like the following.
{
"header": [
{
"fieldType": "STRING",
"readOnly": true,
"headerValue": "name"
},
{
"fieldType": "STRING",
"readOnly": true,
"headerValue": "description"
}
],
"rows": [
[
{
"fieldValue" : "engine"
},
{
"fieldValue" : "this is an engine"
}
],
[
{
"fieldValue" : "engine"
},
{
"fieldValue" : "this is an engine"
}
],
[
{
"fieldValue" : "engine"
},
{
"fieldValue" : "this is an engine"
}
],
[
{
"fieldValue" : "engine"
},
{
"fieldValue" : "this is an engine"
}
]
]
}
A row is for example
[
{
"fieldValue" : "engine"
},
{
"fieldValue" : "this is an engine"
}
]
The number of entries in a row matches the number of header columns. So "engine" is the "name" column and "this is an engine" is the "description" column
When I use GSON to turn my POJO's into a JSON String the closest I have got to match this structure is:
{
"header": [
{
"fieldType": "STRING",
"readOnly": true,
"headerValue": "name"
},
{
"fieldType": "STRING",
"readOnly": true,
"headerValue": "description"
}
],
"rows": [
{
"fieldValues": [
"engine",
"this is an engine"
]
},
{
"fieldValues": [
"engine",
"this is an engine"
]
},
{
"fieldValues": [
"engine",
"this is an engine"
]
},
{
"fieldValues": [
"engine",
"this is an engine"
]
}
]
}
Here's the code I'm using to test
enum FieldType {
STRING,
BOOLEAN,
NUMBER,
PHOTO,
PHOTOLIST;
}
class SurveyFields {
private List<SurveyColumn> header;
private List<SurveyRow> rows;
public List<SurveyColumn> getHeader() {
return header;
}
public List<SurveyRow> getRows() {
return rows;
}
public void setHeader(List<SurveyColumn> header) {
this.header = header;
}
public void setRows(List<SurveyRow> rows) {
this.rows = rows;
}
}
class SurveyColumn {
private FieldType fieldType;
private boolean readOnly;
private String headerValue;
public static class Builder {
private FieldType fieldType;
private boolean readOnly;
private String headerValue;
public Builder withFieldType(FieldType fieldType) {
this.fieldType = fieldType;
return this;
}
public Builder withReadOnly(boolean readOnly) {
this.readOnly = readOnly;
return this;
}
public Builder withHeaderValue(String headerValue) {
this.headerValue = headerValue;
return this;
}
public SurveyColumn build() {
return new SurveyColumn(fieldType, readOnly, headerValue);
}
}
public SurveyColumn(FieldType fieldType, boolean readOnly, String headerValue) {
this.fieldType = fieldType;
this.readOnly = readOnly;
this.headerValue = headerValue;
}
}
class SurveyRow {
public static class Builder {
private String[] fieldValues;
public Builder withFieldValues(String[] fieldValues) {
this.fieldValues = fieldValues;
return this;
}
public SurveyRow build() {
return new SurveyRow(fieldValues);
}
}
private String[] fieldValues;
public SurveyRow(String[] fieldValues) {
this.fieldValues = fieldValues;
}
}
public class TestGson {
public static void main(String[] args) {
SurveyFields fields = new SurveyFields();
fields.setHeader(Arrays.asList(new SurveyColumn[] {
new SurveyColumn.Builder().withHeaderValue("name").withFieldType(FieldType.STRING).withReadOnly(true)
.build(),
new SurveyColumn.Builder().withHeaderValue("description").withFieldType(FieldType.STRING)
.withReadOnly(true).build() }));
fields.setRows(Arrays.asList(new SurveyRow[] {
new SurveyRow.Builder().withFieldValues(new String[] { "engine", "this is an engine" }).build(),
new SurveyRow.Builder().withFieldValues(new String[] { "engine", "this is an engine" }).build(),
new SurveyRow.Builder().withFieldValues(new String[] { "engine", "this is an engine" }).build(),
new SurveyRow.Builder().withFieldValues(new String[] { "engine", "this is an engine" }).build()
}));
Gson gson = new Gson();
System.out.println(gson.toJson(fields));
}
}
How can I structure my POJO's to match the expected JSON output?
If you get the JSON from a third party, this site might help you generate POJO from JSON.

Categories

Resources