Sort JSON data based on nested field - java

I am trying to solve this problem in Java.
I need to read student data in JSON format from a URL and output it after sorting.
The model is:
[
{
"name": "string",
“lecturers”: [
{
"name": "string",
“subject”: "string"
}
]
}
]
Below is an example of what the JSON data looks like:
[
{
"name": “Jack”,
“lecturers”: [
{
"name": “Mr.Smith”,
“subject”: “Music”
},
{
"name": “Mr.Cooper”,
“subject”: “Physics”
},
{
"name": “Miss.Rae”,
“subject”: ""
}
]
},
{
"name": “Dan”,
“lecturers”: [
{
"name": “Miss.Jane”,
“subject”: “Physics”
},
{
"name": “Mr.Smith”,
“subject”: “Music”
},
{
"name": “Mr.JJ”
}
]
},
{
“lecturers”: [
{
"name": “Mr.Higgs”,
“subject”: “Art”
},
{
"name": “Mr.Jones”,
“subject”: “Chemistry”
}
]
}
]
The output should be sorted alphabetically as below:
Subject A
Lecturer X
Student E
Lecturer Y
Subject B
Lecturer A
Student C
Student D
What I have done so far :
As below, read the JSON data using Jackson library's ObjectMapper.
public class Student {
String name;
List<Lecturer> lecturers;
}
public class Lecturer {
String name;
String Subject;
}
List<Student> student = objectMapper.readValue(new URL(“myUrl”), new TypeReference<List<Student>>(){});
How do I go about sorting ? Should I use Java comparator. Not sure how to sort based a field from a list of nested objects. Or should I store the JSON data differently and try to sort ?
Also, as you can see from the example, null values should be handled.

Related

MongoDb aggregation for filtering list based on ids and mapping this filtered list to another field

In my mongodb I have the data as shown below:
{
"classes": [
{
"classId": "SSC",
"studentIds": [
"1"
]
},
{
"classId": "HSC",
"studentIds": [
"2",
"3"
]
}
],
"students": [
{
"_id": "1",
"student": {}
},
{
"_id": "2",
"student": {}
},
{
"_id": "3",
"student": {}
}
],
}
And I want an aggregation query such that it returns the data as shown below:
"classes": [
{
"classId":"SSC",
"students": [
{
"id": "1",
"student": {}
}
]
},
{
"classId":"HSC",
"students": [
{
"id": "2",
"student": {},
},
{
"id": "3",
"student": {}
}
]
}
]
In this I have list of ids. It should filter the students list for that id and take that object and place this object in class array.
I have tried to use mongodb aggregation for this problem. But unfortunately I am not able write query for that. So can we achieve the above scenario using aggregation.
I am using spring boot mongoTemplate.
You can use $map and $filter,
$map input classes array create students field and do $filter in students array and check condition ids in array or not
db.collection.aggregate([
{
$project: {
classes: {
$map: {
input: "$classes",
as: "c",
in: {
classId: "$$c.classId",
students: {
$filter: {
input: "$students",
cond: { $in: ["$$this._id", "$$c.studentIds"] }
}
}
}
}
}
}
}
])
Playground

MapStruct - Create Mapper 2 objects (simple and complex object)

I want to create a 2 objects using mapstruct. 1 is simple POJO but the other is complex POJO that has Java Map-like structure:
Complex object :
{
"property1": {
"type": "boolean",
"value": true,
"valueInfo": {
"info": "Hello"
}
},
"property2": {
"type": "string",
"value": "string234",
"valueInfo": {
"info": "World"
}
}
}
Simple object:
{
"id" : 123,
"name" : "Jon Doe"
}

Java Stream representation of extracting data from jsonobj

I have a service that returns me a response that has the below object
{
"features": [
{
"name": "climateControl"
},
{
"name": "drivingControl"
},
{
"name": "breakeControl",
"type": [
{
"name": "safety"
}
]
},
{
"name": "seatAdjustments",
"type": [
{
"name": "motion"
}
]
},
{
"name": "enginePower",
"type": [
{
"name": "motion"
}
]
}
]
}
Now I need to extract the feature names that are either null or doesn't have any type with name "safety"
I can write something like below
List<Features> features = service.getFeatures();
List<String> refinedList = new ArrayList<>();
for(Feature feature:features){
if(feature.getType==null || feature.getType().getName().equalsIgnoreCase("safety") )
{
refinedList.add(feature.getName());
}
}
Looking for a way to do the same using java streams.
You can use filter for the if conditions and map to getName, then collect as:
List<String> refinedList = features.stream()
.filter(feature -> feature.getType == null || feature.getType().getName().equalsIgnoreCase("safety"))
.map(feature -> feature.getName())
.collect(Collectors.toList());

How to make a JSON Parser to parse elasticsearch mapping in java?

I wanted to parse this structure which is an elasticsearch filter:
{
"filter": {
"name_synonyms_filter": {
"synonym_path": "sample.txt",
"type": "abc_synonym_filter"
},
"name_formatter": {
"name": "name_formatter",
"type": "abc_token_filter"
}
}
}
My question is how can I access individual filters without using key ("name_synonyms_filter" , etc) in java?
your JSON was impropertly formatted.
Here it is fixed:
{
"abc": [{
"name": "somename"
},
{
"name": "somename"
}
]
}
How to parse it:
let x = JSON.parse({
"abc": [{
"name": "somename"
},
{
"name": "somename"
}
]
});
console.log(x);
Let me know if you have any questions.

Spring Data Rest + Spring Data Mongo - can't update numer of elements on list in object

so I have got a problem with updating object which contain a list of elements. My object definition:
public class Project {
private String _id;
private String name;
private List<Pair> config;
}
And the Pair object:
public class Pair {
private String key;
private String value;
}
I'm using Spring Rest repository to provide the Rest Api and everything is stored in mongodb. Just using the simple interface to create mongoRepository
#RepositoryRestResource(collectionResourceRel = "project", path = "projects")
public interface ProjectRepository extends MongoRepository<Project, String>{
Project findByName(String name);
}
When I create a project object with json (sending POST to /projects):
{
"name": "test_project",
"config": [{
"key": "port",
"value": "12"
},{
"key": "port2",
"value": "123"
}]
}
I have got the proper response and object has been created:
{
"_id": "58c916fad76a3a186731ad28",
"name": "test_project",
"createdAt": "2017-03-15T10:27:06.295+0000",
"modifiedAt": "2017-03-15T10:27:06.295+0000",
"config":[
{
"key": "port",
"value": "12"
},
{
"key": "port2",
"value": "123"
}]
}
So right now I would like to send PUT to update my object and I'm getting strange results:
For example sending following body with PUT to
localhost:8151/projects/58c916fad76a3a186731ad28
{
"name": "test_project",
"config": [{
"key": "port",
"value": "12"
}]
}
So I want to remove one element from list. The response is (Status OK):
{
"_id": "58c916fad76a3a186731ad28",
"name": "test_project",
"createdAt": "2017-03-15T10:27:06.295+0000",
"modifiedAt": "2017-03-15T10:27:06.295+0000",
"config":[
{
"key": "port",
"value": "12"
},
{
"key": "port2",
"value": "123"
}]
}
So the number of elements didn't change what I expected (my expectations was that the new list replace the old one). Next test:
I would like to add one new element to list:
{
"name": "test_project",
"config": [{
"key": "port",
"value": "12"
},{
"key": "port1",
"value": "13"
},{
"key": "port2",
"value": "14"
}]
}
Gives following result:
{
"_id": "58c916fad76a3a186731ad28",
"name": "test_project",
"createdAt": "2017-03-15T10:27:06.295+0000",
"modifiedAt": "2017-03-15T10:27:06.295+0000",
"config":[
{
"key": "port",
"value": "12"
},
{
"key": "port1",
"value": "13"
}]
}
New element hasn't been added but the second element has changed.
It looks like instead of List mongo save it as an array and can't change the size but can update the element. Am I right?
But, if it would be true the next test should return the same result:
I'm sending the empty list of config and I'm expect that I will have an two-element list.
{
"name": "test_project",
"config": []
}
But what is strange for me I have got the following result:
{
"_id": "58c916fad76a3a186731ad28",
"name": "test_project",
"createdAt": "2017-03-15T10:27:06.295+0000",
"modifiedAt": "2017-03-15T10:27:06.295+0000",
"config":[]
}
So the number of elements has been updated.
To be honest right now I'm totally confused how it works. Could anyone explain how Spring rest repository handle this action and propose a proper solution for this problem?
I am having the same issue. As a workaround you can send a PATCH request. This updates the array properly.

Categories