Using JAVA Reflection how to create custom JSON object mapping - java

I have a json Object in the below format, I need to assign the values from Json to java object, But the label name in JSON and class is different.
{
FirstName: "Sample",
LastName: "LName",
Address: [
{
type: "Temp",
street: "test stree",
},
{
type: "Perm",
street: "test stree",
}
]
}
Class Parent{
private String Name1;
private String Nama2;
private List<Address> address;}
Class Address{
Private String type;
private String data;
}
I wanted to implement the custom object mapper using Java reflection. the mapping is as below, But I am not getting idea to implement this, Any valuable suggestion or usage of external api would help me to achieve the scenario.
Json Object name Jave Class object Name
FirstName ---------- Name1
LastName ---------- Name2
Address.type ------- Address class type
Address.street ----- Address class data

You would need reflexion if you receive json data with same structure with properties names changing, for example :
{
FirstName1: "Sample",
LastName1: "LName",
Address1: [
{
type1: "Temp",
street1: "test stree",
},
{
type1: "Perm",
street1: "test stree",
}
]
}
{
FirstName2: "Sample",
LastName2: "LName",
Address1: [
{
type2: "Temp",
street2: "test stree",
},
{
type2: "Perm",
street2: "test stree",
}
]
}
In your case, it rather look like a property name matching issue, you can annotate your java pojo like that :
public class Parent{
#JsonProperty("FirstName")
private String Name1;
#JsonProperty("LastName")
private String Nama2;
private List<Address> address;
}
public class Address{
private String type;
#JsonPRoperty("street")
private String data;
}
Finally you can deserialize your json object using standard Jackson library :
new ObjectMapper().readValue(json, Parent.class);

Related

How to deserialize complex JSON to java object

I need to deserialize JSON to java class.
I have JSON like the following:
{
"data": {
"text": "John"
},
"fields":[
{
"id": "testId",
"name": "fieldName",
"options": {
"color": "#000000",
"required": true
}
},
{
"id": "testId",
"name": "fieldName1",
"options": {
"color": "#000000",
"required": false
}
}
]
}
and I need to deserialize this JSON (only "fields" section) to java class like the following:
public class Field {
public final String id;
public final String name;
public final String color;
public final boolean required;
}
and I need to get something like the following:
// The key is the id from field object (it can be the same in the multiple objects.)
Map<String, List<Field>> fields = objectMapper.readValue(json, Map<String, List<Field>>);
How can I do it using Jackson?
As long as jackson doesn't support #JsonWrapped, you have to use the following work around.
First you need to create a custom class which contains the fields:
public class Fields {
public List<Field> fields;
}
Depending on your ObjectMapper configuration you have to add #JsonIgnoreProperties(ignoreUnknown = true) to the Fields class, to ignore any other properties.
Next is that you have to define the nested Options class which is solely used temporarily:
public class Options {
public String color;
public boolean required;
}
And at last add this constructor to your Field class:
#JsonCreator
public Field(#JsonProperty("id") String id, #JsonProperty("name") String name, #JsonProperty("options") Options options){
this.id = id;
this.name = name;
this.color = options.color;
this.required = options.required;
}
The #JsonCreator annotation indicates to jackson that this constructor needs to be used for the deserialization. Also the #JsonProperty annotations are required as arguments to constructors and methods are not preserved in the bytecode
Then you can deserialize your json just like this:
List<Field> fields = objectMapper.readValue(json, Fields.class).fields;

Trouble with converting Json in Java

I'm trying to read in a somewhat complex json string and I'm having problems with nested items and how to retrieve them.
My java code looks like the following
String longJson = "{'Patient': {'Name': {'Given': 'FirstName','Family': 'LastName'},'Gender': 'Female','DOB': '1980-07-04T00:00:00.0000000','AgeInYears': 36,'MartialStatus': 'Single', 'Race': 'Race','Ethnicity': 'Ethnicity','Class': 'Inpatient','Address': {'StreetAddress': 'StreetAddress','City': 'City','State': 'State','ZipCode': 'ZipCode', 'Country': 'Country'}}}";
Gson gson = new Gson();
PrescriptionReq sample = null;
sample = gson.fromJson(longJson, PrescriptionReq.class);
String firstName = sample.getPatient().getName().getGiven();
//String firstName = sample.patient.name.getGiven();
System.out.println("Testing: "+ firstName);
When I run either approach I get a null point exception
Here is the Json in a more readable view
{
"Patient": {
"Name": {
"Given": "FirstName",
"Family": "LastName"
},
"Gender": "Female",
"DOB": "1980-07-04T00:00:00.0000000",
"AgeInYears": 36,
"MartialStatus": "Single",
"Race": "Race",
"Ethnicity": "Ethnicity",
"Class": "Inpatient",
"Address": {
"StreetAddress": "StreetAddress",
"City": "City",
"State": "State",
"ZipCode": "ZipCode",
"Country": "Country"
}
}
}
Here are my classes:
public class PrescriptionReq {
private Patient patient;
public Patient getPatient(){
return patient;
}
public class Patient {
Name name;
Address address;
public Name getName(){
return name;
}
//Other variables
}
public class Name {
private String Given;
private String Family;
public String getGiven() {
return Given;
}
public String getFamily() {
return Family;
}
}
}
I'm not sure if I am storing the json wrong or retrieving it wrong. Any help is much appreciated!
Your field names aren't matching your JSON, and hence you're getting back a PrescriptionReq object with a null patient field.
Off the top of my head, I can think of a couple ways to fix this:
Change the name of the variable to match the JSON field
public class PrescriptionReq {
// have to rename Patient class to avoid name collision
private PRPatient Patient;
...
Add a #SerializedName annotation to tell Gson what the "real" field name is
public class PrescriptionReq {
#SerializedName("Patient")
private Patient patient;
...
Of course you'll also need to do this for the name field in the Patient class, as well as anything in Address you're having problems with.

How to handle multiple json fields in gson

I want to parse a json to an object which gives me details of every entity attached to a bank.
My json looks like :
{
"href" : "abc",
"configurations" :
[
{
"type" : "bank-customer",
"properties" : {
"cust-name" : "foo",
"acc-no" : "12345"
}
},
{
"type" : "bank-employee",
"properties" : {
"empl-name" : "foo",
"empl-no" : "12345"
}
}
]
}
The properties for various entity "type" is different.
Creating a pojo for this is the challenge. My properties.java will have to include all properties irrespective of the type of the property :
public class Configurations {
#SerializedName("type")
#Expose
private String entityType;
#SerializedName("properties")
#Expose
private Properties properties;
}
public class Properties {
#SerializedName("cust-name")
#Expose
private String custName;
#SerializedName("empl-no")
#Expose
private String emplNo;
#SerializedName("empl-name")
#Expose
private String emplName;
#SerializedName("acc-no")
#Expose
private String accNo;
}
This is painful when I have a lot of entity types and property per entity type. Is there any other way I can parse this json into different property objects for different entity types? I am using gson to parse the JSON
Note : I can't make any changes to the json itself.
I completely agree with mauros answer.
But you can also create a interface hierarchy and implement Instance Creator.
Its can be easily solved by using alternate keyword from #SerializedName annotation.
public class Properties {
#SerializedName(value="cust-name", alternate={"empl-name", "user-name"})
#Expose
private String name;
#SerializedName("acc-no", alternate={"empl-no", "user-id"})
#Expose
private String id;
//setter and getters
}

How to filter JSON object

I have a JSON object that is a list of Students that have Name, FName, City, Class, Contact.
Now I want to filter only the objects (Students) which belong to the specific city. Can I filter the mail json object
{
"Students": [
{
"id": 1,
"Name": "Student1",
"FName": "FName1",
"Class": "I",
"City": "Delhi"
},
{
"id": 2,
"Name": "Student2",
"FName": "FName2",
"Class": "II",
"City": "Mumbai"
},
{
"id": 3,
"Name": "Student3",
"FName": "FName3",
"Class": "II",
"City": "Delhi"
},
{
"id": 4,
"Name": "Student4",
"FName": "FName4",
"Class": "III",
"City": "Mumbai"
}
]
}
How can I get sub json list of students belongs to Delhi City?
Using JSONPath the selection would look like this:
JsonPath.read(jsonAsString, "$.Students[?(#.City==Delhi)]")
If you are using Java 8 the following works (note: I am using Jackson, but as long as your JSON library returns a Map object for JSON objects, this example will still work):
// These 2 lines are Jackson specific
ObjectMapper mapper = new ObjectMapper();
Map obj = mapper.readValue(s, Map.class);
List<Object> students = (List<Object>) obj.get("Students");
Object[] delhiStudents = students
.stream()
.filter(student -> ((Map)student).get("City").equals("Delhi"))
.toArray();
you cannot play around much with available Json library, all you can do is to convert it into some POJO or say Map. refer this
Also i found something here as well. It might help you as well.
If you don't mind using a third-party library, you can use GSON. What you have to do is providing a custom deserializer to the Gson object. This deserializer will exclude all the Students objects that have the specific city value in their JSON representation.
public class Test {
public static void main(String[] args) throws Exception {
Type type = new TypeToken<List<Student>>() {}.getType();
Gson gson = new GsonBuilder().registerTypeAdapter(type, new Student.StudentListDeserializer("Mumbai")).create();
List<Student> list = gson.fromJson(new FileReader("myJson.json"), type);
System.out.println(list);
}
}
class Student {
private long id;
private String Name;
private String FName;
private String Class;
private String City;
#Override
public String toString() {
return "Student [id=" + id + ", Name=" + Name + ", FName=" + FName
+ ", Class=" + Class + ", City=" + City + "]";
}
static class StudentListDeserializer implements JsonDeserializer<List<Student>>{
private Set<String> forbiddenCities;
public StudentListDeserializer(String... forbiddenCities) {
this.forbiddenCities = new HashSet<>(Arrays.asList(forbiddenCities));
}
#Override
public List<Student> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
List<Student> list = new ArrayList<>();
for(JsonElement e : json.getAsJsonObject().get("Students").getAsJsonArray()) {
if(!forbiddenCities.contains(e.getAsJsonObject().get("City").getAsString())) {
list.add(context.deserialize(e, Student.class));
}
}
return list;
}
}
}
which outputs:
[Student [id=1, Name=Student1, FName=FName1, Class=I, City=Delhi], Student [id=3, Name=Student3, FName=FName3, Class=II, City=Delhi]]
You can use DSM library. By using it you can filter JSON while you reading JSON data.
Let's say you have POJO class for the student. Fields of student are not exactly matched with JSON data.
Student Class
public class Student {
private long id;
private String name;
private String firstName;
private String className;
private String city;
// getter/setter
}
You will define a yaml file that contains definitions of your mappings between json and Student class.
result:
type: array # result is list
path: /Students
filter: self.data.city=='Delhi' # filter by city field of class
fields:
id: long # id is long and path is the same as json id field.
name:
path: Name
firstName:
path: FName
className:
path: Class
city:
path: City
Use DSM to filter JSON and deserialize to Student class
DSM dsm=new DSMBuilder(new File("student.yaml")).create(Student.class);
List<Student> students= (List<Student>)dsm.toObject(new File("student.json");
Here is students list that converted to json.
[ {
"id" : 1,
"name" : "Student1",
"className" : "I",
"city" : "Delhi",
"firstName" : "FName1"
}, {
"id" : 3,
"name" : "Student3",
"className" : "II",
"city" : "Delhi",
"firstName" : "FName3"
} ]

How to use Jackson ObjectMapper to parse json response to java objects

Here is my Json response
"postedevent": [
{
"status": "true",
"event_id": "800",
"num_of_image_event": "0",
"title": "Testy",
"photo": "http://54.200.110.49/checkplanner/img/upload/21310059819profile_image_1409303464798.png",
"event_date": "2014-08-29",
"fullDate": "Friday - August 29, 2014",
"event_from": "12:00AM",
"event_to": "12:15AM",
"city": "Ahm",
"state": "CA",
"member_id": "471",
"username": "Krishna Mohan",
"pencil": "yes",
"attend": "yes",
"company": "Development"
}
]
this is java class to get java objs from json response
public class PostedEvent {
String status;
int event_id;
int num_of_image_event;
String title;
String photo;
String event_date;
String fullDate;
String event_from;
String event_to;
String city;
String state;
String member_id;
String username;
String pencil;
String attend;
String company;
}
public class PostedEvnetsList
{
ArrayList<PostedEvent> postedevent;
}
And I am parsing in this way
InputStream is = WebResponse.getResponse(url);
ObjectMapper mapper = new ObjectMapper();
PostedEvnetsList mList = null;
mList = mapper.readValue(is,PostedEvnetsList.class);
eventList = mList.postedevent;
I am getting following parse exception
jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "status" (Class com.example.jsonproforexam.PostedEvent), not marked as ignorable
I have declared same fields as in json response then why I am geting this exception
Please help
Your fields of PostedEvent and the PostedEvent field of PostedEventsList are not accessible.
You must set them as public (not recommended) or provide public getters and setters for them POJO-style.
Then Jackson will be able to de-serialize and the error will go away.
You can use the JsonProperty annotation to specify the json key
Ex:
public class PostedEvent {
#JsonProperty("status")
String status;
#JsonProperty("event_id")
String eventId;
....
....
If you have missed some fields from json in your entity class, you can use #JsonIgnoreProperties annotation to ignore the unknown fields.
#JsonIgnoreProperties(ignoreUnknown = true)
public class PostedEvent {
...

Categories

Resources