Using this input
{
"personId": "uhqwe-8ewn-3129m",
"infoPerson": {
"name": "john",
"age" : 35
}
},
....
And this POJO
public class Person {
private String name;
private int age;
//getter/setter
}
I need to read it as
private Map<String,Person> pMap;
using the personId as the map key.
Is there a way to do it with jackson annotation?
As far as I know, it is not possible.
You can read a list and then convert it to a map.
Something like this
Map<String, Person> map = list.stream()
.collect(Collectors.toMap(Person::getPersonId, person -> person));
Related
I am trying to convert JSON into POJO.
I have worked with Jackson to convert standard JSON file.
In this particular case, I would like to overwrite the key value to "default" class/variable. In this case, there are multiple key value to be replaced (ie. hundreds, and the key values to be replaced are unknown).
Is this possible? I thought of storing it into Map, then iterate and store each into POJO, but wondering if there is different option, since I am not that familiar with storing JSON to Map.
Example of the JSON to be processed:
"People" : {
"person1" : {
"name" : "john doe",
"address" : "123 main st",
"email" : "john#doe.com"
},
"person2" : {
"name" : "bob cat",
"address" : "234 dog st",
"email" : "bob#cat.com"
},
"person3" : {
"name" : "foo bar",
"address" : "111 1st ave",
"email" : "foo#bar.com"
},
"person8" : {
"name" : "james bono",
"address" : "999 alaska st",
"email" : "james#bono.com"
}
}
Is it possible to generate the class in the following structure? The main issue is there are hundreds of value to be replaced and assuming they are unknown, I can't use this approach.
#JsonIgnoreProperties(ignoreUnknown = true)
public class People {
#JsonAlias({"person1", "person2"})
private List<Details> person; // --> this should be the default replacing person1, person2, and so on
private class Details {
String name;
String address;
String email;
}
}
You can use JsonAnySetter annotation for all properties personXYZ. See below example:
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
System.out.println(mapper.readValue(jsonFile, People.class).getPersons());
}
}
class People {
private List<Details> persons = new ArrayList<>();
#JsonAnySetter
public void setPerson(String name, Details person) {
this.persons.add(person);
}
public List<Details> getPersons() {
return persons;
}
public static class Details {
String name;
String address;
String email;
// getters, setters, toString
}
}
For your JSON above code prints:
[Details{name='john doe', address='123 main st', email='john#doe.com'}, Details{name='bob cat', address='234 dog st', email='bob#cat.com'}, Details{name='foo bar', address='111 1st ave', email='foo#bar.com'}, Details{name='james bono', address='999 alaska st', email='james#bono.com'}]
In case you use inner class remember to make it public static to make it visible to Jackson instantiation process.
See also:
How to use dynamic property names for a Json object
Jackson Annotation Examples
Just adding my two cents. I think this way looks nicer and is also easy to retrieve data. Jackson will do the deserialization without the need of any other tags or custom code, and it's all nice and sorted in a hashmap.
class People {
private Map<String, Person> persons = new HashMap<>();
// getter and setters
}
public class Person {
String name;
String address;
String email;
// getters and setters
}
}
I'm wondering if there is any way to deserialize several JSON fields to just one Java property. E.g. given this JSON:
{
"id" : "1",
"name" : "Bartolo",
"address" : "whatever",
"phone" : "787312212"
}
deserialize it to this class:
public class Person {
public String id;
public String name:
#JsonProperty(names = {"address", "phone"}) //something like this
public String moreInfo;
}
so moreInfo equals to "whatever, 787312212" or something similar.
Is this possible without using custom deserializer?
You could use the #JsonCreator annotation like following:
String json = {"id" : "1", "name" : "Bartolo", "address" : "whatever", "phone" : "787312212" }
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue(json , Person.class);
and in the constructor of your Person class add this
#JsonCreator
public Person(#JsonProperty("address") String address, #JsonProperty("phone") String phone) {
this.moreInfo = address + "," phone;
}
Another solution, if you don't want to know/handle other fields in the object, but decided to still receive these fields (maybe for logging purposes), then you can put them in a key-value store(Map)
#Getter
private final Map<String, Object> otherFields = new HashMap<>();
#JsonAnySetter
public void set(String name, Object value) {
otherFields.put(name, value);
}
Note that if you have any field with the same name as the Map field(like 'otherFields' in the example above), then you can get MismatchedInputException
Lets say we have the following JSON example:
{
"teachers": [{
"id": "abc",
"payment": 10,
"name": "xyz",
"clases": ["1", "3"]
}, {
"id": "qwe",
"payment": 12,
"name": "xcv",
"classes": ["1", "2"]
}],
"classes": [{
"id": "1",
"room": 7
}, {
"id": "2",
"room": 1
}, {
"id": "3",
"room": 2
}]
}
I would like to deserialize it to Java objects (getters/setters ommited):
class Teacher {
private String id;
private double payment;
private String name;
private List<CLassRoom> classRooms;
}
class ClassRoom {
private String id;
private int room;
}
As you see, we have a references here. I know I can deserialize it with Jackson (and would like to) but the problem is that I cannot touch DTO itself (so annotations are not possible, would also like to avoid wrappers (many classes)). Also, it would be nice if the "configuration" of deserialization was in separate file (json schema for example). I would also like to avoid some tags given by user - he should only pass me the values. Moreover, he should know where is the error, if he made some mistake.
Also, it would be nice if I could manipulate name of field in json (some clients may have different habits).
I didn't find anything which satisffied all of above requirements(entity reference and error handling are the most important). However - I just have heard about json schema, so maybe it provides such functionality (but I didn't find it though). Any helpful reference/example/lib? I will appreciate any help.
Just to be correct - imagine that the given json is a RELATIONAL database snapshot of the instance. I just want to create whole entity like the hibernate (or actually JPA) does :)
1. add jar of import org.json.JSONObject.
2. JSONObject object = new JSONObject(list)
2.1 object.has("teachers") if it is exists
2.2 JSONArray teacherArray = (JSONArray) object.get("teachers");
2.3 JSONObject teacherJsonObject = teacherArray .getJSONObject(0);
(if you have more than jsonobject in json arrary then itrate it.)
2.4 if(teacherJsonObject .has("id"))//you can check existence like this.
String id=teacherJsonObject .getString("id");
String payment=teacherJsonObject .getString("payment");
String name=teacherJsonObject .getString("name");
It may not be the best solution, but it's a working one.
Let's create a Parser class like the following:
public class Parser {
private List<Teacher> teachers;
private List<ClassRoom> classes;
public void parse() {
for (Teacher teacher : teachers) {
for (String classRoomId : teacher.getClasses()) {
for (ClassRoom classRoom : classes) {
if (classRoom.getId().equals(classRoomId)) {
teacher.getClassRooms().add(classRoom);
}
}
}
}
}
}
Modify your ClassRoom class to have a getter on the id field:
public class ClassRoom {
private String id;
private int room;
public String getId() {
return id;
}
}
And your Teacher class to get the Ids of classes AND the classRooms references:
public class Teacher {
private String id;
private double payment;
private String name;
private String[] classes;
private List<ClassRoom> classRooms = new ArrayList<>();
public String[] getClasses() {
return classes;
}
public List<ClassRoom> getClassRooms() {
return classRooms;
}
}
If you use the Gson library, you could then just parse your JSON like that:
Gson gson = new Gson();
Parser parser = gson.fromJson(jsonString, Parser.class);
parser.parse;
Now, every teacher will have their classRooms correctly referenced.
I am not very good with Java, so please forgive me for my ignorance.
I am selecting from a table and looping through the result set to make a list that i can use to convert into json which should look like the following example.
{
"ContactId": "123",
"key": {
"type": "email",
"email": "emailAdress"
},
"address": "String",
"source": "String",
"revoked": true,
"text": "String"
}
I don't know how to put them into a list as there are different datatypes i need to put into hash maps.
Please note, in the exmaple above key is an object and i am trying to achieve the same thing in the list.
The ultimate goal is to covert the generated list into json.
I have created a few hashmaps but i don't think i am doing it the right way.
String Table = "TableName";
String sql = String.format("SELECT id_user, email FROM %s ", Table);
ResultSet res = dbConn.prepareStatement(sql).executeQuery();
Map<String, Map> keyObject = new HashMap<String, Map>();
Map<String, String> keyMap = new HashMap<String, String>();
Map<String, String> mainMap = new HashMap<String, String>();
List<Map<String, String>> contacts = new ArrayList<>();
int i = 0;
while(res.next()){
keyMap.put("type", "email");
keyMap.put("value", res.getString("email"));
keyObject.put("key", keyMap);
mainMap.put("tenant", res.getString("id_user"));
mainMap.put("purpose", "Marketing sendouts");
mainMap.put("legalBase", "Withdrawn");
contacts.add(i, map);
i++;
}
System.out.println(contacts);
Instead of using generic structures like List or Map, you'd be better off designing classes which model the structure you need. For instance, in the case above you'll probably have something like:
public class Contact {
private int contactId;
private ContactKey key;
private String address;
private String source;
private boolean revoked;
private String text;
// ....
}
Now this is a strongly typed structure which can be easily filled from the resultset. A tool like Jackson (or many others) can easily render it as JSON.
Create a Model Class and use it's getter and setter methods.
Eg.
public class Model {
private String id;
private String name;
//Use constructor
public Model(String id, String name) {
this.id = id;
this.name = 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;
}
}
// Now make your Map data Structure center code hereustom .
Hashmap<String,Model> Map = new Hashmap();
// Create a object of your custom Model datastructure and add data.
Model model = new Model("145","Jason");
Map.put("1st",model);
Note that all the data is store at "1st" key of Map.
Kudos.... Enjoy
If map is your preferred data structure, you can use the code below:
Map<String, Object> map = new HashMap<>();
map.put("ContactId", 123);
Map<String, Object> keyMap = new HashMap<>();
keyMap.put("type", "email");
keyMap.put("email", "emailAdress");
map.put("key", keyMap);
map.put("address", "aaaa");
ObjectMapper objectMapper = new ObjectMapper();
try {
String json = objectMapper.writer().withDefaultPrettyPrinter().writeValueAsString(map);
System.out.println(json);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
I am assuming Jackson is the library you use for serialization.
Let's assume we have JSON object like this:
{
"employees" : {
"Mike" : 23,
"Bill" : 42,
"Jimmy" : 30
}
}
And the next classes:
public class Employees {
private List<Employee> employees;
}
public class Employee {
private String name;
private int age;
}
Have we any ways to deserialize the json to Employees type object?
List can be used to deserialize array of elements [...] but {...} is object. If you want you can consider using Map instead of List
class Data {
Map<String,String> employees;
}
...
Gson gson = new Gson();
Data data = gson.fromJson(json, Data.class);
for (Map.Entry<String, String> emp: data.employees.entrySet())
System.out.println(emp.getKey()+" -> "+emp.getValue());
Output:
Mike -> 23
Bill -> 42
Jimmy -> 30
If you would like to parse your json using these classes
public class Employees {
private List<Employee> employees;
}
public class Employee {
private String name;
private int age;
}
Your data should look like:
{
"employees" : [
{"name":"Mike", "age": 23},
{"name":"Bill", "age": 42},
{"name":"Jimmy", "age": 30}
]
}
You can use Jackson's ObjectMapper class to deserialize JSON like so: https://stackoverflow.com/a/6349488/2413303