Map just ONE object to another (DTO) with Java8 - java

can you tell me if exist some pretty way to map one entity object to another dto object? When I needed convert List<ObjEntity> to List<ObjDTO> I created that function:
public class Converter {
public static Function<ObjEntity, ObjDTO> MYOBJ_ENTITY_TO_DTO = objEntity -> {
ObjDTO dto = new ObjDTO();
dto.setId(objEntity.getId());
dto.setName(objEntity.getName());
dto.setNote(objEntity.getNote());
// ...
return dto;
};
}
and I use it like this:
List<ObjDTO> dtos = objEntitiesList.stream().map(Converter.MYOBJ_ENTITY_TO_DTO).collect(Collectors.toList());
But what if I need convert just ONE object? Should I use that function MYOBJ_ENTITY_TO_DTO for that and how? Or what is the best practice? Yes, I can do classical function in Converter class like that:
public static ObjEntity dtoToEntity(ObjDTO dto) {
// map here entity to dto and return entity
}
but it is old style. Exist some new practice in java 8? Something similar like my example for list by lambda?

ObjDTO dto = MYOBJ_ENTITY_TO_DTO.apply(entity);
I see the other way around more often: instead of MYOBJ_ENTITY_TO_DTO, define entityToDto as a method and use
List<ObjDTO> dtos = objEntitiesList.stream().map(Converter::entityToDto).collect(Collectors.toList());
for lists.

Related

Java - Gson not working with Object defined on the fly

I would like not to define an extra type just to make the json conversion. I am using a library that needs an object as an input and then performs http operations with this data, so I cannot use a hard coded json string as input.
private static final Gson GSON = new Gson();
public static void main(String[] args) {
System.out.println(GSON.toJson(new Object() {
private String email_address = "me#mail.eu";
public String getEmail_address() {return "me#mail.eu"; }
public void setEmail_address(String mail) {email_address = mail; }
}));
}
I tried to remove getter and setter or leave the getter and remove the field but it doesn't work. Anybody knows how to fix this?
Libraries for Json serialization/deseralization like Gson, count on the fact that you have defined your custom object on which you will map the json string. This is because they use reflection on the class to map the fields with the corresponding keys in the json. Without it, it is difficult that they can achieve anything(usable).
Why not define an extra type ? We are not in the 1980s. I would personnally use a DTO. What is Data Transfer Object?
But maybe the answer to you question reside here : Java - Does Google's GSON use constructors?

Is it possible to parse JSON data of one complex object to custom object via API

I have a web project with 2 Java Entities(Lets Say E1,E2) like how mybatis and VO works.
Object structure:
class E1{
String a;
.... n other data members
E2 e2;
}
class E2{
String b;
.... n other data members
}
Is it possible to make a single class in Android project, i.e.
class E1 {
String a;
String b; //This Data member belongs to class E2
}
and parse it with the help of a framework (like Jackson) or I have to write a custom class for that?
My JSON Data will look like this:
{
"E1": {
"a": "some data",
.
.
.
"E2": {
"b": "some data",
.
.
other data
}
}
}
Is there any API which can do this?
I asked this because with my web Application its not just 2 Class but atleast 10 interconnected class and I am not Using them in my android app. So don't wanna replicate the same classes in android app.
Also if you can suggest any other possible way.
It would be a very bad design practice/approach, making things very difficult to debug, error prone and not future proof (think about it, what if you add to one of the 10 classes a field that conflict with another class' field?).
Anyway, if you still want to trick your way out of the correct approach that would be to have 10 classes, I am not aware of any lib that provides you with this feature. You could parse json ==> 10 Java Map, then merge the 10 Map through the Map::putAll method and finally pass the obtained Map that contains all the objects to Jackson.
Your best bet is to use #JsonAnySetter annotation from Jackson library on the receiver POJO.
public class E1{
public String a;
private Map<String, Object> paramMap = new HashMap<>();
#JsonAnyGetter
public Map<String, Object> getParamMap() {
return paramMap;
}
#JsonAnySetter
public void setParamMap(String s, Object o) {
paramMap.put(s, o);
}
}
This will put every unimplemented attributes in a HashMap.
In combination with #JsonAnyGetter, the serialization of the receiver POJO will give the same result as the JSON input.

How to set class attributes from list of objects in Java 8

I have one ArrayList of PageSummary object and I want to be set value from list object to my Model class attributes using java 8.
public class XXXX {
for(PageSummary ps : pageSummaryList){
model = new Model();
model.setName(ps.getName());
model.setContent(getContent(ps.getName()));
model.setRating(getAverageRating(ps.getName()));
modelList.add(model);
}
private String getContent(String sopName){}
private AverageRatingModel getAverageRating(String sopName){}
}
Here getAverageRating function return integer between 1-5 and getContent return string.
Here are some hints:
create a PageSummary stream from the list
map from PageSummary to Model
collect the Model object
Here are some tutorials:
https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html
https://docs.oracle.com/javase/tutorial/collections/streams/index.html
First, you should create a Model constructor with a PageSummary argument.
public Model(PageSummary ps) {
this.setSopName(ps.getName());
this.setSopContent(getContent(ps.getName(), clientCode, context, httpcliet));
this.setAverageRating(getAverageRating(ps.getName(), clientCode, context, httpclient));
}
Thanks to this, you can shorten the loop:
for (PageSummary ps : pageSummaryList) {
ModelList.add(new Model(ps));
}
And easily use the Stream API:
// This solution is thread-safe only if ModelList is thread-safe
// Be careful when parallelizing :)
pageSummaryList.stream().map(Model::new).forEach(ModelList::add);
or
// A thread-safe solution using Stream::collect()
List<Model> models = pageSummaryList.stream()
.parallel() // optional :)
.map(Model::new)
.collect(Collectors.toList());
ModelList::addAll(models); // I suppose you don't need us to implements this one!
Thanks Alexis C. for pointing out that using the collect approach avoid concurrency issues in case of parallelization :)

Return anonymous object in java

In JavaScript we can do:
function foo() {
...
return {
attr1 : ... ,
attr2 : ...,
};
}
But what is its equivalent in Java?
Because I want to return a custom Json object from my controller after an ajax call and I want to create a new bean.
As Java dictates, you should create a new class and convert it to JSON. Also, you can use Map<String,Object> to accomplish the same thing. To generate following JSON:
{
"attr1":1,
"attr2":2
}
you can use following code:
Map<String,Object> map = new HashMap<>(3);
map.put("attr1", 1);
map.put("attr2", 2);
and convert it to JSON.
P.S.: HashMap in Java causes your heap to increase and unnecessary garbage, so I specified just enough size to keep two elements.

How to Convert Map to Object

I have a Map Object and the data in map is like
col1 -> data1, col2 -> data2, col3 -> data3 ...
Is it possible to convert this Map to Java Object like
class MapObj {
String col1 = "data1";
String col2 = "data2";
String col3 = "data3";
}
Whilst it is possible to create classes at runtime with custom class loaders, it is relatively pointless. How would you access the fields (other than reflection and other dynamically created classes)?
use Jackson
import com.fasterxml.jackson.databind.ObjectMapper;
public class Foo {
{
ObjectMapper objectMapper = new ObjectMapper();
YourObject obj = objectMapper.convertValue(YourMap, YourObject.class);
}
}
BeanUtils.populate(entry,map);
Are there a fixed set of named entries in the Map? If so, you can just create the MapObj class as you have it and assign the three fields by saying myMapObj.col1 = myMap.get("col1"); and so on.
But stepping back from this question for a moment, what's the larger problem you're trying to solve? A Map itself is actually a very convenient container for this data already, so perhaps you can just use the Map for the same purpose that you were planning to use MapObj for?
I don't see any point in putting a bunch of Map values to a class.
If you want static access, why not try the opposite:
class MapAccess {
Map<String, String> backingMap = ...
public String getCol1() {
return backingMap.get("col1");
}
public String getCol2() {
return backingMap.get("col2");
}
public String getCol3() {
return backingMap.get("col3");
}
}
This way, you'r application doesn't need to know about the Map and you don't get lost with reflection.
I don't know of any pre-made libs that will do it for you, but it should be quite trivial using the java.lang.reflect API. Specifically, the Field#set* methods. Of course, however, you would need to have a pre-defined class with the fields (keys) defined.

Categories

Resources