How to filter JSON object - java

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"
} ]

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"
} ]
}

Using JAVA Reflection how to create custom JSON object mapping

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);

How to convert custom object with map field that includes list of custom object to json? [duplicate]

This question already has answers here:
Converting Java objects to JSON with Jackson
(9 answers)
Closed 3 years ago.
Let's say, I have an Employee class which looks like this:
public class Employee{
Map<String, ArrayList<Salary>> salary = new HashMap<String, ArrayList<Salary>>();
String name;
String age;
}
public class Salary{
String amount;
String currency;
}
What is the smartest way of convertion to/from Json in Java?
Or;
What if my json should look like that:
{
"name": "Test",
"age": "12",
"salary": {
"first": {
"41130": {
"amount": "100",
"currency": "€"
},
"41132": {
"amount": "100",
"currency": "€"
}
},
"second": {
"41129": {
"amount": "100",
"currency": "€"
}
}
}
}
When i tried to convert this to Employee I am getting error below.
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_ARRAY but was BEGIN_OBJECT
public class Main {
public static void main(String[] args) {
Gson gson = new Gson();
Map<String, ArrayList<Salary>> sal = new HashMap<String, ArrayList<Salary>>();
ArrayList<Salary> salaries = new ArrayList<Salary>();
Salary salary1 = new Salary("100", "€");
Salary salary2 = new Salary("200", "€");
salaries.add(salary1);
salaries.add(salary2);
sal.put("1", salaries);
Employee employee = new Employee(sal, "Test", "12");
System.out.println("Age -> " + employee.getAge());
System.out.println("Name -> " + employee.getName());
System.out.println("Salary -> " + employee.getSalary());
String json = gson.toJson(employee);
System.out.println("Json -> " + json);
Employee employee1 = gson.fromJson(json, Employee.class);
System.out.println("Age1 -> " + employee1.getAge());
System.out.println("Name1 -> " + employee1.getName());
System.out.println("Salary1 -> " + employee1.getSalary());
}
#Data
#AllArgsConstructor
#NoArgsConstructor
public static class Employee{
Map<String, ArrayList<Salary>> salary = new HashMap<String, ArrayList<Salary>>();
String name;
String age;
}
#Data
#AllArgsConstructor
#NoArgsConstructor
public static class Salary{
String amount;
String currency;
}
}
Smartest way, if you plan to use that JSON on a web environment is to use Jackson, JAXB or anything your infraestructure already provides, e.g. Let your preferred REST infrastructure do the job for you.
You will need to provide more context on what is the purpose of your application or the required architecture.
I think you can use Jackson ObjectMapper
https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/ObjectMapper.html#writeValue(java.io.OutputStream,%20java.lang.Object)
ObjectMapper objectMapper = new ObjectMapper();
Employee employee = new Employee();
objectMapper.writeValue(new FileOutputStream("data/output.json"), employee);

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 represent sub-documents in JSON array as Java Collection using Jackson?

I would appreciate any help to know the best way to deserialize the following JSON response which we receive from Salesforce into a Java object using Jackson Annotations.
"records": [
{
"attributes": {
"type": "Lead",
"url": "/services/data/v30.0/sobjects/Lead/00Qi000000Jr44XEAR"
},
"Id": "00Qi000000Jr44XEAR",
"Name": "Kristen Akin",
"Address": {
"city": null,
"country": "USA",
"state": "CA",
"stateCode": null,
"street": null
},
"Phone": "(434) 369-3100",
},
{
"attributes": {
"type": "Lead",
"url": "/services/data/v30.0/sobjects/Lead/00Qi000000Jugv2EAB"
},
"Id": "00Qi000000Jugv2EAB",
"Name": "Sarah Jones",
"Address": {
"city": null,
"country": null,
"state": "CA",
"stateCode": null,
"street": null
},
"Phone": "(408) 338-6066",
}
]}
The above JSON response is an array which contains 2 elements. I would like to represent this JSON structure as a Java Collection using Jackson, something like:
#JsonProperty("records")
ArrayList<LinkedHashMap<?, ?>> recordList
The above object representation deserializes the JSON response and represent as a Key-Value pair in HashMap but issue is representing "attributes" and "Address" subdocuments. In the above HashMap their value is being represented as the respective JSON subdocument whereas I would prefer to have Attributes subdocument gets mapped to an Attribute object and similarly Address subdocument mapped to an Address object in the HashMap, something like:
Key Value
attributes <Attributes> object
Id 00Qi000000Jr44XEAR
.....
Address <Address> object
Phone (434) 369-3100
After doing some Google search, I figured I might have to use #JsonTypeInfo and #JsonSubTypes attributes as mentioned in this link.
However, I could not figure how to use these annotations in this specific scenario. Appreciate any help on this.
If the structure of your JSON input is completely dynamic, you can read it as JsonNode or even as Map. Refer to this link for more info.
If you want to map your JSON to java classes but you don't know all the attributes in compile type, you can leverage the #JsonAnyGetter/#JsonAnySetter annotations. Here is an example based on your JSON that stores the unknown attributes for the Address class in the internal map.
public class JacksonMapping {
public static final String JSON = "...";
public static class Attributes {
public String type;
public URI url;
}
public static class Address {
public String city;
public String country;
public String state;
public Integer stateCode;
public String street;
private final Map<String, Object> otherAttributes = new HashMap<>();
#JsonAnySetter
public void setProperty(String name, Object value) {
otherAttributes.put(name, value);
}
#JsonAnyGetter
public Map<String, Object> getOtherAttributes() {
return otherAttributes;
}
}
public static class Record {
#JsonProperty("Id")
public String id;
#JsonProperty("Name")
public String name;
public Attributes attributes;
#JsonProperty("Address")
public Address address;
#JsonProperty("Phone")
public String phone;
}
public static class RecordList {
public List<Record> records;
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
RecordList recordList = mapper.readValue(JSON, RecordList.class);
System.out.println(mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(recordList));
}
}
I can also try to generate java objects from your JSON with a help from a tool. For example this one: http://www.jsonschema2pojo.org

Categories

Resources