Datastructure to store an nested element in JSON - java

I am modelling classes in Java to store a JSON , for a particular JSON
"id":1,
"firstName":"sample",
"lastName":"person",
"Books":{
"bookName":"gone with the wind"
"isbn": 12345
}
I created a class person with int id , String firstName etc...
what would be the best way to store bookName , make a class Books with a String bookName and int isbn , how would I represent books in the person class , As an array? since books always has only one value is there a better way to represent it

For json serialization/deserialization, I suggest the jackson library.Here is my code,it works fine on my computer!
I store the json in the file named json.data as following:
{"id":1,
"firstName":"sample",
"lastName":"person",
"books":[{"bookName":"gone with the wind","isbn":12345}]
}
And the code,I omitted the getter/setter to be short
public class Book
{
private String bookName;
private int isbn;
}
public class BookWriter
{
private String id;
private String firstName;
private String lastName;
private Book[] books;
}
public class JSONTest
{
public static void main(String[] args)
{
try
{
ObjectMapper mapper = new ObjectMapper();
BookWriter writer=(BookWriter)mapper.readValue(new File("json.data"), BookWriter.class);
for(Book book:writer.getBooks())
{
System.out.println(book.getBookName()+","+book.getIsbn());
}
} catch (Exception e)
{
e.printStackTrace();
}
}
}

Related

How to sort and create hash string using LinkedHashMap?

I am developing an application within that I have to create the SHA256 hash for the incoming data. To make that I have to follow the specific sorting order for each property. Hence, I have created a class TemplateNodeMap which extends LinkedHashMap, within that I have specified the order that I need to follow.
Now, I would like to read each property in the incoming JSON data, add a specific field, and create the Hash string. I am a bit confused about adding the data and creating the string. I am worried if I am following the optimal procedure or not as I need to follow the process for a large amount of data.
Can someone please let me know if this is the right approach?
Following is the incoming JSON (Since JSON can have any order I need to obtain properties according to my required Hash String order):
{
"age": 30,
"name": "Batman",
"address": {
"city": "Gotham",
"street": {
"name": "Gotham 123"
}
}
}
Following is my TemplateNodeMap class:
package io.hash;
import java.util.LinkedHashMap;
public class TemplateNodeMap extends LinkedHashMap {
public TemplateNodeMap() {
put("name", null);
put("age", null);
put("address", new LinkedHashMap<>() {{
put("street", new LinkedHashMap<>() {{
put("name", null);
}});
put("city", null);
}});
}
}
Following is my ApplicationMain class which is reading and loading the data to TemplateNodeMap:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
import java.io.InputStream;
public class ApplicationMain {
public static void main(String[] args) throws IOException {
final ObjectMapper objectMapper = new ObjectMapper();
final InputStream jsonStream = ApplicationMain.class.getResourceAsStream("/InputJSON.json");
final ObjectNode inputTemplate = objectMapper.readValue(jsonStream, ObjectNode.class);
System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(inputTemplate));
final TemplateNodeMap templateNodeMap = new TemplateNodeMap();
templateNodeMap.put("name", inputTemplate.get("name"));
templateNodeMap.put("age", inputTemplate.get("age"));
//Unable to understand how to insert the complex object values into LinkedHashMap and follow the order
}
}
I am not understanding how to add the complex object to LinkedHashMap and create a string out of it.
Not all fields are mandatory so I would like to omit the null values during the creation of Hash String.
Can someone please suggest to me how to achieve this and if this is the right approach to creating a Hash String based on the required order?
There are two jackson annotations that can help you to serialize the jackson properties in a custom order excluding the non null values:
JsonPropertyOrder annotation that can be used to define ordering (possibly partial) to use when serializing object properties.
JsonInclude annotation used to indicate when value of the annotated property, or all properties of the annotated class, is to be serialized.
You can then deserialize your json to the pojo java classes and then serialize them obtaining a new json with the expected order of the properties and without null properties:
#Data
#JsonPropertyOrder(value = {"name", "age", "address"})
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Person {
private int age;
private String name;
private Address address;
}
#Data
#JsonPropertyOrder(value = {"street", "city"})
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Address {
private String city;
private Street street;
}
#Data
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Street {
private String name;
}
//you can delete for example the name property from your json
Person person = mapper.readValue(json, Person.class);
String output = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(person);
//ok, the name property will not appear in the output because it's null
System.out.println(output);
Requirements:
"I am developing an application within that I have to create the SHA256 hash for the incoming data."
"To make that I have to follow the specific sorting order for each property."
Proposal:
Create data classes for your incoming data, order their attributes as you like
Transform data class into a 'standard' JSON representation using prettyprint
Calculate hash over 'standard' JSON representation
For completeness a manual parsing of the linked hashmap is included
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.*;
import java.nio.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.*;
class Person {
int age; String name; Address address; // Attribute order effects output order!
public Person(){}
public Person(int age, String name, Address address) {
this.age = age; this.address = address; this.name = name;
}
public void setAge(int age){this.age = age;}
public int getAge(){return age;}
public void setName(String name){this.name = name;}
public String getName(){return name;}
public void setAddress(Address address){this.address = address;}
public Address getAddress(){return address;}
}
class Address {
String city;
Street street;
public Address(){}
public Address(String city, Street street){this.city = city; this.street = street;}
public void setCity(String city){this.city = city;}
public String getCity(){return city;}
public void setStreet(Street street){this.street = street;}
public Street getStreet(){return street;}
}
class Street {
String name;
public Street(){}
public Street(String name) {this.name = name;}
public String getName(){return name;}
public void setName(String name) {this.name = name;}
}
public class ApplicationMain {
static String inputJson = "{\"age\": 30,\"name\": \"Batman\",\"address\": {\"city\": \"Gotham\",\"street\": {\"name\": \"Gotham 123\"}}}";
public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
final ObjectMapper objectMapper = new ObjectMapper();
try {
// use Paths.get("InputJSON.json").toFile() as alternative to the string
Map<?, ?> map = objectMapper.readValue(inputJson, Map.class);
System.out.println("The linked hashmap to process for sorting:");
System.out.println(map);
System.out.println("Individual elements:");
System.out.println("name: " + map.get("name"));
System.out.println("age: " + map.get("age"));
System.out.println("address:");
Map<?, ?> addressMap = (Map<?, ?>)map.get("address");
System.out.println(" city: " + addressMap.get("city"));
System.out.println(" street:");
System.out.println(" name: " + ((Map<?, ?>)addressMap.get("street")).get("name"));
} catch (Exception ex) {
ex.printStackTrace();
}
Person person = objectMapper.readValue(inputJson, Person.class);
System.out.println("Original JSON:\n" + inputJson);
String prettyJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(person);
System.out.println("Standardized JSON:\n" + prettyJson);
byte[] hash = MessageDigest.getInstance("SHA-256").digest(prettyJson.getBytes(StandardCharsets.UTF_8));
for ( byte b : hash) {
System.out.printf("%02x", b);
}
System.out.println();
}
}
$ java -cp .:jackson-databind-2.13.3.jar:jackson-core-2.13.3.jar:jackson-annotations-2.13.3.jar ApplicationMain
The linked hashmap to process for sorting:
{age=30, name=Batman, address={city=Gotham, street={name=Gotham 123}}}
Individual elements:
name: Batman
age: 30
address:
city: Gotham
street:
name: Gotham 123
Original JSON:
{"age": 30,"name": "Batman","address": {"city": "Gotham","street": {"name": "Gotham 123"}}}
Standardized JSON:
{
"age" : 30,
"name" : "Batman",
"address" : {
"city" : "Gotham",
"street" : {
"name" : "Gotham 123"
}
}
}
5f962abf0cdc5150eb2614c629592d889d59b82499b13dd1b8d12e421bb0440a
$
You can check the hash value at https://dencode.com/hash
(The link already contains the JSON data. If you paste text there, verify that the correct line ending type is selected.)

How to get an arrayJSON in webService Rest?

I am developing a WEb Service Rest in java, netbeans.
This is the JSON I want to receive:
{
"ticket":"2132158645161654561651616",
"avaliacoes":[
{
"id":1,
"nome":"Atendimento",
"nota":5,
"observacoes":"testeTEste"
},
{
"id":2,
"nome":"Atendimento",
"nota":5,
"observacoes":"testeTEste"
}
]
}
Reception Class
#PUT
#Consumes(MediaType.APPLICATION_JSON)
#Path("venda/enviardados")
public String postVenda(#QueryParam("key") String key, #QueryParam("serial") String serial, VendaAvaliacao va) {
...
}
Entity Classes
public class VendaAvaliacao {
private int id;
private String ticket;
//private List<VendaAvaliacaoInner> avaliacoes = new ArrayList<>(); //I've tried it too
private VendaAvaliacaoInner[] teste;
}
public class VendaAvaliacaoInner {
private int id;
private String nome;
private int nota;
private String observacao;
}
The ticket is received and populated, but array = null.
I've read other similar topics but they did not help .... how can I do?
https://pt.stackoverflow.com/questions/6046/convers%C3%A3o-de-string-json-para-objeto-java?rq=1
https://pt.stackoverflow.com/questions/159725/receber-valor-de-array-json-para-string-java
https://pt.stackoverflow.com/questions/290759/como-obter-objetos-de-um-array-de-json-usando-jsonarray-no-java
Maybe the service REST you are consuming don't populate the data in the array.
As an advice i would work with List<T> rather than T[]
Also i see that you are mapping 3 properties in you object but the id property don't exist in raw JSON isn't it ?

Create Object from set of json properties jackson

Please refer below example.
public class Human {
private String name;
private int age;
}
public class Teacher {
private String school;
private Human human;
}
And JSON looks like :
{
"school": "My School",
"age": 20,
"name": "My Name"
}
I want to create Teacher from JSON string which has Human as inner object but should match to same level of JSON properties.
I'm using Jackson API to create java object from JSON.
You can mark the human field as #JsonUnwrapped:
public class Teacher {
private String school;
#JsonUnwrapped
private Human human;
// constructor / setters
}
public class Human {
private String name;
private int age;
// constructor / setters
}
public class Test {
String str = "{ \"school\": \"My School\", \"age\": 20, \"name\": \"My Name\" }";
System.out.println(new ObjectMapper().readValue(str, Teacher.class));
}
That will de-serialize into the format you're looking for.

How can I unwrap a specific field in a JSON using Jackson?

I have a JSON payload that looks like this:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"primary_image": {
"id": 247,
"zoom_url": "www.site.com/in_123__14581.1393831046.1280.1280.jpg",
"thumbnail_url": "www.site.com/in_123__14581.1393831046.220.290.jpg",
"standard_url": "www.site.com/in_123__14581.1393831046.386.513.jpg",
"tiny_url": "www.site.com/in_123__14581.1393831046.44.58.jpg"
}
}
Can I unwrap a specific field and discard all the others? In other words, can I bind this directly to a POJO like this:
public class Product {
private Integer id;
private String name;
private String standardUrl;
}
There are lots of ways. Do you need to deserialize, serialize or both?
One way to deserialize would be to use a creator method that takes the image as a tree node:
public static class Product {
private Integer id;
private String name;
private String standardUrl;
public Product(#JsonProperty("id") Integer id,
#JsonProperty("name") String name,
#JsonProperty("primary_image") JsonNode primaryImage) {
this.id = id;
this.name = name;
this.standardUrl = primaryImage.path("standard_url").asText();
}
}
The creator doesn't have to be a constructor, you could have a static method that is only used for Jackson deserialization.
You'd have to define a custom serializer to reserialize this, though (e.g. a StdDelegatingSerializer and a converter to wrap the string back up as an ObjectNode)
There are different ways to skin this cat, I hope you can use Jackson 2 for this, since it offers great ways to deserialize Json data, one of my favorites deserialization features is the one I'll show you here (using Builder Pattern) because allows you to validate instances when they are being constructed (or make them immutable!). For you this would look like this:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.Map;
#JsonDeserialize(builder = Product.Builder.class)
public class Product {
private Integer id;
private String name;
private String standardUrl;
private Product(Builder builder) {
//Here you can make validations for your new instance.
this.id = builder.id;
this.name = builder.name;
//Here you have access to the primaryImage map in case you want to add new properties later.
this.standardUrl = builder.primaryImage.get("standard_url");
}
#Override
public String toString() {
return String.format("id [%d], name [%s], standardUrl [%s].", id, name, standardUrl);
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Builder {
private Integer id;
private String name;
private Map<String, String> primaryImage;
public Builder withId(Integer id) {
this.id = id;
return this;
}
public Builder withName(String name) {
this.name = name;
return this;
}
#JsonProperty("primary_image")
public Builder withPrimaryImage(Map<String, String> primaryImage) {
this.primaryImage = primaryImage;
return this;
}
public Product build() {
return new Product(this);
}
}
}
To test it I created this class:
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
String serialized = "{" +
" \"id\": 32," +
" \"name\": \"[Sample] Tomorrow is today, Red printed scarf\"," +
" \"primary_image\": {" +
" \"id\": 247," +
" \"zoom_url\": \"www.site.com/in_123__14581.1393831046.1280.1280.jpg\"," +
" \"thumbnail_url\": \"www.site.com/in_123__14581.1393831046.220.290.jpg\"," +
" \"standard_url\": \"www.site.com/in_123__14581.1393831046.386.513.jpg\"," +
" \"tiny_url\": \"www.site.com/in_123__14581.1393831046.44.58.jpg\"" +
" }" +
" }";
ObjectMapper objectMapper = new ObjectMapper();
try {
Product deserialized = objectMapper.readValue(serialized, Product.class);
System.out.print(deserialized.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
The output is (using the override toString() method in Product:
id [32], name [[Sample] Tomorrow is today, Red printed scarf], standardUrl [www.site.com/in_123__14581.1393831046.386.513.jpg].
There are two ways to get the response you required. For both methods, we are going to use JsonView.
Create two types of JsonView:
public interface JViews {
public static class Public { }
public static class Product extends Public { }
}
First method
#JsonView(JViews.Public.class)
public class Product {
private Integer id;
private String name;
#JsonIgnore
private Image primaryImage;
#JsonView(JViews.Product.class)
public String getStandardUrl{
return this.primaryImage.getStandardUrl();
}
}
Second way
Using Jackson's #JsonView and #JsonUnwrapped together.
#JsonView(JViews.Public.class)
public class Product {
private Integer id;
private String name;
#JsonUnwrapped
private Image primaryImage;
}
public class Image {
private String zoomUrl;
#JsonView(JViews.Product.class)
private String standardUrl;
}
#JsonUnwrapped annotation flattens your nested object into Product object. And JsonView is used to filter accessible fields. In this case, only standardUrl field is accessible for Product view, and the result is expected to be:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"standard_url": "url"
}
If you flatten your nested object without using Views, the result will look like:
{
"id": 32,
"name": "[Sample] Tomorrow is today, Red printed scarf",
"id":1,
"standard_url": "url",
"zoom_url":"",
...
}
Jackson provided #JsonUnwrapped annotation.
See below link:
http://jackson.codehaus.org/1.9.9/javadoc/org/codehaus/jackson/annotate/JsonUnwrapped.html

Specific information from json string

I've been playing around with tweets in Eclipse for a while, which are presented as a json string.
To this end, I've created an object called Tweet (original, huh?) which takes certain information from the json string, and stores it in the Tweet object. Nothing fancy.
My Tweet class looks as follows:
public class Tweet implements TwitterMelding {
public Tweet() {
}
String created_at;
String id;
String text;
String user;
public void setUser(String user) {
this.user = user;
}
public void setText(String text) {
this.text = text;
}
public void setId(String id) {
this.id = id;
}
public void setCreated_at(String created_at) {
this.created_at = created_at;
}
}
Now, simple as it may look, there is one of those that doesn't work.
Specifically String user. What it's suppose to do, is store user ID of the person who posted the tweet.
The following is the tweet as obtained from Twitter in all it's horrible length:
{"created_at":"Sat Feb 08 15:37:37 +0000 2014","id":432176397474623489,"id_str":"432176397474623489","text":"Skal begynne \u00e5 selge vekter.. Eneste m\u00e5ten det konstant kommer penger i lommen","source":"\u003ca href=\"http:\/\/twitter.com\/download\/iphone\" rel=\"nofollow\"\u003eTwitter for iPhone\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":366301747,"id_str":"366301747","name":"skinny-pete","screen_name":"JFarsund","location":"bj\u00f8rge","url":null,"description":"j\u00f8rgen er en tynn gutt med pack.. Men det teller vel ikke? Det gj\u00f8r vel ikke bio heller","protected":false,"followers_count":427,"friends_count":291,"listed_count":2,"created_at":"Thu Sep 01 23:03:49 +0000 2011","favourites_count":5103,"utc_offset":3600,"time_zone":"Copenhagen","geo_enabled":true,"verified":false,"statuses_count":8827,"lang":"no","contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/pbs.twimg.com\/profile_background_images\/378800000089578611\/6840970475350d63190eb05d3d7e47ec.png","profile_background_image_url_https":"https:\/\/pbs.twimg.com\/profile_background_images\/378800000089578611\/6840970475350d63190eb05d3d7e47ec.png","profile_background_tile":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/431961396528414720\/EwkxQBkW_normal.jpeg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/431961396528414720\/EwkxQBkW_normal.jpeg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/366301747\/1391822743","profile_link_color":"0084B4","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":{"type":"Point","coordinates":[60.33700829,5.24626808]},"coordinates":{"type":"Point","coordinates":[5.24626808,60.33700829]},"place":{"id":"2260fcb4a77f2bad","url":"https:\/\/api.twitter.com\/1.1\/geo\/id\/2260fcb4a77f2bad.json","place_type":"city","name":"Bergen","full_name":"Bergen, Hordaland","country_code":"NO","country":"Norge","contained_within":[],"bounding_box":{"type":"Polygon","coordinates":[[[5.1602697,60.1848543],[5.1602697,60.5335445],[5.6866852,60.5335445],[5.6866852,60.1848543]]]},"attributes":{}},"contributors":null,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"symbols":[],"urls":[],"user_mentions":[]},"favorited":false,"retweeted":false,"filter_level":"medium","lang":"no"}
It really is a long eye-sore.
I've added a few "..." to the next one, to make it slightly more readable, only showing the value I'm interested in:
{…,"user":{"id":366301747,"id_str":"366301747","name":"skinny-pete","screen_name":"JFarsund","location":"bj\u00f8rge","url":null,"description":"j\u00f8rgen er en tynn gutt med pack.. Men det teller vel ikke? Det gj\u00f8r vel ikke bio heller","protected":false,"followers_count":427,"friends_count":291,"listed_count":2,"created_at":"Thu Sep 01 23:03:49 +0000 2011","favourites_count":5103,"utc_offset":3600,"time_zone":"Copenhagen","geo_enabled":true,"verified":false,"statuses_count":8827,"lang":"no","contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/pbs.twimg.com\/profile_background_images\/378800000089578611\/6840970475350d63190eb05d3d7e47ec.png","profile_background_image_url_https":"https:\/\/pbs.twimg.com\/profile_background_images\/378800000089578611\/6840970475350d63190eb05d3d7e47ec.png","profile_background_tile":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/431961396528414720\/EwkxQBkW_normal.jpeg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/431961396528414720\/EwkxQBkW_normal.jpeg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/366301747\/1391822743","profile_link_color":"0084B4","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null}, …}
Right, still with me?
As I mentioned above, what I want is the users ID, which I want assigned to the variable "user" in the Tweet object.
{…,"user":{"id":366301747,"id_str":"366301747",… }…}
All I want is to assign the number 366301747, to the variable "user" in my Tweet object.
But for the life of me, I cannot seem to.
To make sure the Tweet object gets the info it wants and not the info it doesn't, I am using a Jackson object:
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
So my question.
How do I tell Tweet to take the 366301747 number from my json string and assign it to the variable "user"?
I'd prefer it doable with Jackson alone, and not having to import more JARs than necessary.
Please forgive the wall of text.
It can be pretty straightforward with Gson library.
Since, you've already done the hard work of creating the pojo, by looking at your json you can validate that User is a valid json object and not a String value.
Hence, let's modify your pojo's (Tweet) user attribute a little with:
User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
Where User custom class is:
public class User {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Now just call the your Gson method to convert your object from the json (I stored the json to a file and read it through a BufferedReader):
public static void main(String[] args) throws FileNotFoundException {
Gson gson = new Gson();
BufferedReader br = new BufferedReader(new FileReader(
"json.txt"));
Tweet tweetObj = gson.fromJson(br, Tweet.class);
System.out.println(tweetObj.getUser().getId());
}
Output:
366301747
EDIT: Based on the comments, solution using jackson - 2 options
Keep newly created User class, the ObjectMapper code remains exactly the same and System.out.println(tweet.getUser().getId()) gets you the userid.
If User class is not to be used, change your Tweet to look like this:
Code:
public class Tweet {
String created_at;
String id;
String text;
Map<String, String> user;
public String getCreated_at() {
return created_at;
}
public void setCreated_at(String created_at) {
this.created_at = created_at;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Map<String, String> getUser() {
return user;
}
public void setUser(Map<String, String> user) {
this.user = user;
}
}
And print the userid in the calling method as:
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
Tweet tweet = mapper.readValue(br, Tweet.class);
System.out.println(tweet.getUser().get("id"));
Gets you:
366301747
You can change the setUser method to take a Map and set user.id manually:
public void setUser(Map<String, Object> props) {
user = props.get("id").toString();
}

Categories