ArrayList Grouping By specific conditions - json

I have these POJO
class LocaleBook
{
private String bookId;
private String bookName;
private Locale locale;
//setters & getters
}
class Locale
{
private String country;
private String language;
//setters & getters
}
Sample data for the above is
"alice", "Alice in the wonderland", "GB", "en"
"matrix", "The Matrix", "TH", "en"
"christtree", "The Christmas Tree", "GB", "en"
And this method:
List<LocaleBook> localeBooks = repo.getLocalBooks();
I want to group data together by country and language and i created this POJO:
class NewPoJo
{
private String country;
private String language;
private List<KeyValuePair> localeBooks = new HashSet<>();
//setters & getters
}
class KeyValuePair {
private String label;
private String value;
//setters & getters
}
Expected output:
[
{
"country":"GB",
"language":"en",
"localeBooks":[
{
"label":"alice",
"value":"Alice in the wonderland"
},
{
"label":"christtree",
"value":"The Christmas Tree"
}
]
},
{
"country":"TH",
"language":"en",
"localeBooks":[
{
"label":"matrix",
"value":"The Matrix"
}
]
}
]
I tried Collectors.groupingBy by country and language but seems like it will create something like following which is not i want. How can i make it to the expected output i want?
{
"GB_en": [
{
"label": "alice"
"value": "Alice in the wonderland"
},
{
"label": "christtree"
"value": "The Christmas Tree"
}
]
}

You can do it by toMap collector with merge function:
list.stream().collect(Collectors.toMap(LocaleBook::getLocale,
lb -> new NewPoJo(lb.getLocale().getCountry(), lb.getLocale().getLanguage(),
new ArrayList<>(Collections.singletonList(new KeyValuePair(lb.getBookId(), lb.getBookName())))),
(a, b) -> {
a.getLocaleBooks().addAll(b.getLocaleBooks());
return a;
}))
.values();
just you should override equals and hashCode methods in the Locale class.

Related

how to parse a json similar string and map it into a pojo

I am trying to map the following JSON to my POJO using Jackson. I have the following JSON and following POJOs. kindly let me know how to map the JSON to POJO.
JSON string :
{
"Application": {
"id": "0",
"name": "MyApp",
"users": [
{
"User": {
"id": "2",
"name": "Beth Jones"
}
}
],
"groups": [
{
"Group": {
"id": "1",
"name": "SimpleGroup",
"users": [
{
"User": {
"id": "2",
"name": "Beth Jones"
}
}
]
}
}
]
}
}
The POJO according to the client specification is below :
package com.example.custom;
//import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.example.Application;
import com.example.Group;
import com.example.User;
import java.util.Collection;
//#JsonIgnoreProperties(ignoreUnknown = true)
public class MyApplication extends Application {
private Collection<User> users;
private Collection<Group> groups;
public MyApplication(String id, String name) {
super(id, name);
}
public void setUsers(Collection<User> users) {
this.users = users;
}
public void setGroups(Collection<Group> groups) {
this.groups = groups;
}
#Override
public Collection<User> getUsers() {
return this.users;
}
#Override
public User getUser(String userId) {
for (User user: MyParser.myApp.getUsers()) {
if (user.getId().equals(userId))
return user;
}
return null;
}
#Override
public Collection<Group> getGroups() {
return this.groups;
}
#Override
public Group getGroup(String groupId) {
for (Group group: MyParser.myApp.getGroups()) {
if (group.getId().equals(groupId))
return group;
}
return null;
}
#Override
public String toString() {
return "MyApplication{" +
"users=" + users +
", groups=" + groups +
'}';
}
}
Mapping Logic :
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MyParser.myApp = mapper.readValue(rewriter.getText(),MyApplication.class);
The resulting object is not able to capture anything as it is all null. Kindly help. Thanks in advance.
I think you should model your JSON correctly, In the users list you shouldn't specify it again that the key is User, that should be preassumed that a list of users will only contain user, same goes for groups list.
IMHO the JSON should look something like this :
{
"application": {
"id": "0",
"name": "MyApp",
"users": [ . ==> Since this is a user List, it will definitely contains user.
{
"id": "2",
"name": "Beth Jones"
}
],
"groups": [
{
"id": "1",
"name": "SimpleGroup",
"users": [
{
"id": "2",
"name": "Beth Jones"
}
]
}
]
}
}
Now the POJO also needs some modification, I am just adding the bare-minimum POJO.
class Application { <====== Top Level Class
private Long id;
private String name;
private List<User> users; // Application has some Users
private List<Group> groups; // Application has some groups
}
class User {
private Long id;
private String name;
}
class Group {
private Long id;
private String name;
private List<User> users; // Each group has some associated users.
}
Now you can use any standard JSON library for Java and convert your JSON into POJO. This will simplify your structure and you won't face null issues with this structure.

how to represent JSON as treeview in Javafx

I have a Film model like below:
public class Film{
private String name;
private String category;
private Actor[] actors;
private MarketingPlan marketingPlan;
}
class Actor{
private String name;
private double salary;
}
class MarketingPlan{
private String nameOfPlan;
private Country[] affectedCountries;
}
class Country{
private int countryID;
private String marketingText;
}
which generate a JSON like this:
{
"name": "My First Film",
"category": "action",
"marketingPlan": {
"name": "plan1",
"affectedCountries": [
{
"marketingText": "This is a marketing text",
"countryID": 332
}
]
},
"actors": [
{
"name": "John",
"salary": 123456
}
]
}
I would like to represent my JSON result above as tree structure in JavaFX. Can anyone give me some hint or suggest me some tutorial how can I do it. Thank you very much in advanced!

Custom field name for fields created from json schema

I have to create a json schema such that when i create class from it, The field name are different from the json keys.
I want to map the json keys to custom fields in the domain object created using this schema
Consider the json scheme
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "sample_master",
"title": "Person",
"type": "object",
"name":"SampleMasterFile",
"properties": {
"first_Name": {
"type": "string"
},
"SYM_CD": {
"type": "string"
// "name":"symCdValue" -> some trick here so that when the domain is created, the field name corresponding to SYM_CD is symCdValue
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
}
},
"required": ["first_Name", "SYM_CD","age"],
"additionalProperties" : false
}
And this is the generated class from the above schema. I want the field generated for json key SYM_CD to be mapped to symCdValue
#JsonInclude(JsonInclude.Include.NON_EMPTY)
#JsonPropertyOrder({
"first_Name",
"SYM_CD",
"age"
})
public class SampleMaster {
#JsonProperty("first_Name")
private String firstName;
#JsonProperty("SYM_CD")
private String sYMCD; // I want this field to be named as symCdValue ?
#JsonProperty("age")
#JsonPropertyDescription("Age in years")
private Integer age;
#JsonProperty("first_Name")
public String getFirstName() {
return firstName;
}
#JsonProperty("first_Name")
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#JsonProperty("SYM_CD")
public String getSYMCD() {
return sYMCD;
}
#JsonProperty("SYM_CD")
public void setSYMCD(String sYMCD) {
this.sYMCD = sYMCD;
}
#JsonProperty("age")
public Integer getAge() {
return age;
}
#JsonProperty("age")
public void setAge(Integer age) {
this.age = age;
}
// Removed to string, equals method
}

Spring Boot (Jackson): How to avoid class name being serialized to JSON

I am consuming some XML exposed from a REST application and want to expose this as JSON in my own REST service.
Right now I have the following POJO:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"salesMarket"
})
#XmlRootElement(name = "salesMarkets")
public class SalesMarkets {
protected List<SalesMarket> salesMarket;
public List<SalesMarket> getSalesMarket() {
if (salesMarket == null) {
salesMarket = new ArrayList<SalesMarket>();
}
return this.salesMarket;
}
}
Which produces the following JSON:
"salesMarkets": {
"salesMarket": [
{
"brands": {
"brand": [
"DAN"
]
},
"code": "999"
},
{
"brands": {
"brand": [
"DAN"
]
},
"code": "208"
}
]
}
My question is (using Jackson annnotations), is there a way to avoid the class name being serialized as JSON??, so I instead would have:
"salesMarket": [{
"brands": {
"brand": [
"DAN"
]
},
"code": "999"
}, {
"brands": {
"brand": [
"DAN"
]
},
"code": "208"
}]
I'm thinking some Jackson annotaion on the class SalesMarkets... But havn't been succesfull yet :-(
UPDATE:
Just realised that the SalesMarket class was referenced from another class - which is why the "salesMarkets" appears in the JSON. Is there a way to annotate the SalesMarkets field, so that it is ignored but not the fields contained there in?:
#XmlRootElement(name = "product")
public class Product {
#XmlElement(required = true)
protected String propertyID;
#XmlElement(required = true)
protected String season;
**protected SalesMarkets salesMarkets;**
protected Information information;
protected Features features;
protected Location location;
protected Address address;
protected Buildings buildings;
protected Pictures pictures;
protected Media media;
protected Prices prices;
protected Offers offers;
protected Availabilities availabilities;
protected Services services;
protected Concepts concepts;
...
You need to either remove
#XmlRootElement(name = "salesMarkets")
Or disable the feature on ObjectMapper:
objectMapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true)
To further unwrap salesMarkets field in Product instances you can do the following:
public class Product {
protected SalesMarkets salesMarkets;
public List<SalesMarket> getSalesMarkets(){
if(salesMarkets != null){
return salesMarkets.getSalesMarket();
} else {
return null;
}
}
}

What is the convenient way to deserialize JSON(links + embedded container) using spring-hateoas?

colleagues!
We want to write Rest Client to service which follow the HATEOAS principle. So we have the following HAL+JSON representation and we want to deserialize it using spring-hateoas :
{
"id": "1",
"title": "album title",
"artistId": "1",
"stockLevel": 2,
"_links": {
"self": {"href": "http://localhost:8080/rest/albums/1"},
"artist": {"href": "http://localhost:8080/rest/artist/1"}
},
"_embedded": {
"albums": [{ //can be array or object
"id": "1",
"title": "album title",
"artistId": "1",
"stockLevel": 2,
"_links": {
"self": {"href": "http://localhost:8080/rest/albums/1"}
}
}],
"artist": { //can be array or object
"id": "1",
"name": "artist name",
"_links": {
"self": {"href": "http://localhost:8080/rest/artist/1"}
}
} //....
}
}
We expected the java object like this:
HalResource {
Resource<Album> //entity
List<Link> // _links
List<Resource<BaseEntity>>{ //_embedded
Resource<Album>
Resource<Artist>
....
}
}
So we have custom resource representation with embedded(list of resources) and entity(single resource):
#XmlRootElement(name = "resource")
public class HalResource<EntityType, EmbeddedType> extends Resources<EmbeddedType> {
#JsonUnwrapped
private EntityType entity;
public HalResource() {
}
public HalResource(Iterable<EmbeddedType> content, Link... links) {
super(content, links);
}
public EntityType getEntity() {
return entity;
}
public void setEntity(EntityType entity) {
this.entity = entity;
}
}
DTO classes:
public abstract class BaseEntity{}
#XmlRootElement(name = "album")
public class Album extends BaseEntity {
private String id;
private String title;
private String artistId;
private int stockLevel;
// getters and setters...
}
#XmlRootElement(name = "artist")
public class Artist extends BaseEntity {
private String id;
private String name;
// getters and setters...
}
And we want to get something like this, where Entity will be Artist or Album, but HalResourcesDeserializer return Resource.class with null content.
HalResource<Album, Resource<Entity>> resources =
restClient.getRootTarget().path("albums/1").queryParam("embedded", true).request().accept("application/hal+json")
.get(new GenericType<HalResource<Album, Resource<Entity>>>() {});
By using #JsonTypeInfo and #JsonSubTypes anotations we successfully deserialized our JSON(you can see the example on the github), but we don't want to have some additional type filds and anotattions in our DTO and JSON format.
We see one solution that is create a custom deserializer which can processing that.
So the question is: What is the convenient way to deserialize our JSON(links + embedded container) using spring-hateoas?
We use spring-hateoas 0.16v(but we tried 0.19v) and glassfish jersey 2.22.1
Thank you!