How to convert an Object to a custom DTO - java

Im having some issues trying to convert a List of Object to a custom DTO. However, all the answers that i found are focused on converting Entities or POJ0s to DTO. How can i do this in either some kind of iteration, or even manyally accesing all the Object properties?
Right now i have something like this that throw some casting errors, but idk if changing datatypes would work or if i should try something else.
List<Object> ls = myDAO.getSomethingFromDB();
List<MyDTO> ls2 = new ArrayList<MyDTO>();
for(Object o : ls){
ls2.add((MyDTO) o);
}
Also, first StackOverflow questing, sorry if im asking something dumb or in a bad way.

You can't directly convert Object to MyDTO until unless myDAO.getSomethingFromDB(); is returning list of MyDTO
Learn more about ClassCastException here:
https://docs.oracle.com/javase/8/docs/api/java/lang/ClassCastException.html
Explanation of ClassCastException in Java
if you really want to convert to MyDTO then you need to create new MyDTO object then set the values to this object.

There are probably a lot of ways to do this, here is one of those ways using Java Streams:
List<MyObject> objects = // Get objects from database
List<MyDto> dtos = objects.stream().map(myObj -> {
MyDto newDto = new MyDto();
// Set your properties here, in this example i'm setting a name and description:
newDto.setName(myObj.getName());
newDto.setDescription(myObj.getDescription());
// Repeat for every property
return newDto;
})
.collect(Collectors.toList());
I am using the map function to create a new DTO with the same properties as my object in the list.

Related

MapStruct - Map list of objects in single object

I am getting a list of objects from 3rd party but it will always contain one object only. So at my end in target I have created it as an object rather than list. That object contains multiple lists inside it just like source object.
This is how I am trying to map a list to an object. ChargeTransaction contain orderInvoice as an object and not a list. For list which are inside ChargeTransaction I have created separate mappers. I dont want to write java code in #afterMapping because then how nested lists will be mapped. The nested lists are of type in both the objects.
#Mapping(target = "orderInvoice", source = "basePaymentRequest.invoice.eventPayload.orderInvoices")
ChargeTransaction createInvoiceCTMapper(PaymentTriggerBaseModel basePaymentRequest, ChargeType chargeType);
Error
java: Can't map property "List<OrderInvoice> basePaymentRequest.invoice.eventPayload.orderInvoices" to "OrderInvoice orderInvoice". Consider to declare/implement a mapping method: "OrderInvoice map(List<OrderInvoice> value)".
I tried
#Mapping(target = "orderInvoice", expression= "java(basePaymentRequest.invoice.eventPayload.orderInvoices.get(0))")
But it gives error in Impl class
chargeTransaction.setOrderInvoice( basePaymentRequest.invoice.eventPayload.orderInvoices.get(0) );
java: incompatible types: com.sams.oms.ng.common.models.payment.request.OrderInvoice cannot be converted to com.sams.oms.ng.common.models.payment.cosmos.OrderInvoice
IMHO the best way to solve this problem is to use a #Named paired with #Mapping#qualifiedByName
#Mapper
class Mapper {
#Mapping(target = "orderInvoice", source ="basePaymentRequest.invoice.eventPayload.orderInvoices", qualifiedByName="firstElement")
ChargeTransaction createInvoiceCTMapper(PaymentTriggerBaseModel basePaymentRequest, ChargeType chargeType);
#Named("firstElement")
OrderInvoice map(List<OrderInvoice> value) {
if(value == null) return null;
if(value.isEmpty()) return null;
return map(value.get(0));
}
abstract com.sams.oms.ng.common.models.payment.request.OrderInvoice map(com.sams.oms.ng.common.models.payment.cosmos.OrderInvoice invoice);
}
In this way you are instructed MapStruct to use map(List<>) to convert invoices to a single OrderInvoice and abstract map(OrderInvoice) to let MapStruct autogenerate mapping code.
Code in untested because I haven't limited spare time today,but I hope my example may be useful;if anything is wrong feel free to comment and I will correct code asap.

how to add attribute at any place in json using JsonObject in java

I have a json. Lets say:
{
"id":"101",
"name":"Saurabh",
"age":"28"
}
Now, I want to add "rollNo":"52" just after id attribute.
How can I do that using jsonNode in java?
Actually I am parsing this object using jsonNode, so no pojo mapping
I just want a way to add the attribute anywhere with creating a pojo mapping.
JsonNode is immutable and is intended for parse operation. However, it can be cast into ObjectNode and add value ((ObjectNode)jsonNode).put("rollNo", "52");
JSON properties are not ordered. You cannot decide to put one "just after" another. They will be in the order they will be.
Well, that's how it's meant. If you use a Jackson streaming JSON Writer, you can use it to write the properties in the order you like. But that's jumping through hoops just to do something that you shouldn't want to do in the first place. When you want stuff in a specific order, put them in arrays.
I actually found a way to do that.
First create a new blank node, then iterate over original node and check your condition and put the new node accordingly.
This may take only fraction of time, but will resolve these kind of issues.
Here is the code
ObjectNode newChildNode = new ObjectNode(JsonNodeFactory.instance);
Iterator<Map.Entry<String, JsonNode>> fields = childNode.fields();
while(fields.hasNext()){
Map.Entry<String, JsonNode> entry = fields.next();
newChildNode.putPOJO(entry.getKey(), entry.getValue());
if("id".equals(entry.getKey())){
newChildNode.put("rollNo", "52");
}
}
//This will convert the POJO Node again to JSON node
ObjectMapper mapper = new ObjectMapper();
newChildNode= mapper.readTree(newChildNode.toString());

How to convert object of any class to a Map in Java?

In Spring MVC we have to use org.springframework.ui.Model instance to pass model to a view. It is not strongly-typed and we have to dynamically build the object like this:
model.addAttribute("departmentID", departmentID);
model.addAttribute("departmentName", departmentName);
model.addAttribute("employees", employees);
However, I came from ASP.NET MVC, where I passed strongly-typed objects to a view, and I had ViewDepartment class which had departmentID, departmentName and employees fields, and I simply passed instance to a view. Here it doesn't work, but I still need to use ViewDepartment class, because I occasionally send it as response to AJAX-requests.
So, to get this working in Spring MVC, I need to translate ViewDepartment object to instance of org.springframework.ui.Model, one way is to build org.springframework.ui.Model from HashMap:
Model.addAllAttributes(Map<String,?> attributes)
The question is, how to build Map<String,?> attributes from instance of ViewDepartment class? Creating HashMap object and manually setting each attribute from each property is not option, because it`s not DRY. I need some way to do this with any class, because I have other model classes in other controllers.
Or, may be, someone can tell another solution to this task, related to Spring MVC specifically.
you could use reflection to get a map of all fields and their values. Be aware, that this gets complicated, if you have nested structures, but with the given example it should work,
public Map<String, Object> toMap( Object object ) throws Exception
{
Map<String, Object> map = new LinkedHashMap<>();
for ( Field field : object.getClass().getDeclaredFields() )
{
field.setAccessible( true );
map.put( field.getName(), field.get( object ) );
}
return map;
}

Javascript Object to Java List

I have the following type of JSON I want to send to Java (I'm using Jersey and the default JSON Parser it comes with)
{ "something" : "1", "someOtherThing" : "2" , ... }
But instead of creating an Object with all these properties in Java, I would like to have a Single HashMap (or whatever) that will allow me to still have access to the Key and the Value
Is such a thing possible?
I don't really have any code that does the transformation, I use Jersey like this
#POST
#Path("/purchase")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public StatusResult purchase(UserPurchaseRequest upr) {
}
If i put properties something and someOtherThing as Strings in my UserPurchaseRequest object, everything will come in fine, but I want to have everything in one structure (because I don't know how many values I will get, and I need their names as well)
Yes, it is possible. But still, it depends on what JSON java API you are using. For example using Jackson JSON you can create HashMap json string like this
ObjectMapper obj = new ObjectMapper();
String json = pbj.writeValue(<HashMap object>);
or vice-versa
HashMap obj = obj.readValue(json, HashMap.class);
Note - org.codehaus.jackson.map.ObjectMapper
You just need to add a Property to your Object like this
private HashMap<String,String> purchaseValues;
Jersey takes care of the rest, for some reason while you are debugging, most of the entries appear as null in the HashMap

How to use Wobly serializer on Android

I'm looking for the alternatives to serialize objects in my Android project. I found Wobly which seem to be fast and small. I understand how to create Wobly wrappers using WoblyImpl but I'm totally confused with how to write/read these objects from the file system? When to run WoblyGenerator and can it be done within my code? Can someone post a code example?
Wobly doesn't support unknown Object fields. So fields like:
Object a;
List<Object> b;
Map<Integer, Object> c;
cannot be serialized with Wobly.
It supports all primitive classes (and their boxed counterparts), all Wobly classes, any Array/List/Map combination of the above.
So in your case, problem is that JSONArray implements List<Object>. If you know what kind of object JSONArray holds, for example List<Map<Integer, String>>, you can write:
class Example extends WoblyImpl {
#WoblyField(id = 0)
List<Map<Integer, String>> array;
public void setArray(JSONArray json) {
array = (List)json;
}
}
Though after deserialization you will get ArrayList<HashMap<Integer,String>> and not JSONArray back.
If you don't know what object JSONArray is holding, it would be painful to make it work with Wobly, if at all possible. You can check out comprehensive comparison of serialization libraries here:
https://github.com/eishay/jvm-serializers/wiki
OK, I got it. If you wondered here and want to know how to do it here are the steps:
Create your class by extending WoblyImpl and annotate the fields according to the instructions
Then run WoblyGenerator.updateSourceFolder("c:/foo/src"); where the parameter is directory containing your file (or package). I created a small project in Eclipse for that but you can also run this from the command line using supplied wobly-generator.jar
This step will inject serialization code into your source file which will include read and write methods
Gotcha: this didn't work for smart-json JSONObject or JSONArray or for HashMap. The error I got is this:
java.lang.IllegalArgumentException: next type for class net.minidev.json.JSONObject of index 0, class java.lang.Class
at com.wowd.wobly.generation.WoblyGeneratorUtils.extractNextType(WoblyGeneratorUtils.java:91)
at com.wowd.wobly.generation.types.impl.MapTypeCodeGenerator.defaultTypeFormat(MapTypeCodeGenerator.java:163)
at com.wowd.wobly.generation.types.TypeCodeHandler.defaultTypeFormat(TypeCodeHandler.java:121)
at com.wowd.wobly.generation.WoblyGeneratorUtils.adjusFormatForCompressed(WoblyGeneratorUtils.java:317)
at com.wowd.wobly.generation.WoblyCodeGenerator.generateWriteFieldCode(WoblyCodeGenerator.java:178)
at com.wowd.wobly.generation.WoblyCodeGenerator.generateWriteMethod(WoblyCodeGenerator.java:270)
at com.wowd.wobly.generation.WoblyCodeGenerator.generateFieldsAndMethods(WoblyCodeGenerator.java:647)
at com.wowd.wobly.generation.WoblyCodeGenerator.generateRegularCode(WoblyCodeGenerator.java:721)
at com.wowd.wobly.generation.WoblyCodeGenerator.generateCode(WoblyCodeGenerator.java:677)
at com.wowd.wobly.updater.GenerateAndReplace.update(GenerateAndReplace.java:130)
at com.wowd.wobly.updater.GenerateAndReplace$1.execute(GenerateAndReplace.java:198)
at com.wowd.wobly.updater.GenerateAndReplace$1.execute(GenerateAndReplace.java:1)
at com.wowd.common.functions.impl.FilterProcedure.execute(FilterProcedure.java:40)
at com.wowd.wobly.updater.SourceFilesVisitor.visitDir(SourceFilesVisitor.java:69)
at com.wowd.wobly.updater.SourceFilesVisitor.visitDir(SourceFilesVisitor.java:60)
at com.wowd.wobly.updater.SourceFilesVisitor.visitDir(SourceFilesVisitor.java:60)
at com.wowd.wobly.updater.SourceFilesVisitor.visitDir(SourceFilesVisitor.java:60)
at com.wowd.wobly.updater.SourceFilesVisitor.visitPackage(SourceFilesVisitor.java:38)
at com.wowd.wobly.updater.GenerateAndReplace.updateInPackage(GenerateAndReplace.java:190) WoblyParcel error
at com.wowd.wobly.WoblyGenerator.updatePackage(WoblyGenerator.java:60)
at com.wowd.wobly.WoblyGenerator.updateSourceFolder(WoblyGenerator.java:49)
at Generator.main(Generator.java:19)
If someone can tell me how to fix that - post it as a separate answer and I'll accept it

Categories