I have a list of objects populated and I need to populate more attributes from a Object.
Considering using mapperstruct and I can't modifying previous atributes of Objects from a target list.
// type for obj in list target
public class ObjectExampleA {
private String id;
private String firstAttr;
private String secondAttr;
private String thirdAttr;
}
// target list
// List<ObjectExampleA> listTarget;
// at this point considering an elements in list like this...
// {"id":1, "firstAttr":"blue", "secondAttr":"black", "thirdAttr": null}
// {"id":2, "firstAttr":"gray", "secondAttr":"red", "thirdAttr": null}
// source obj
public class ObjectExampleB {
private String thirdAttr;
}
// I need to populate all thirdAttr atribute of all elements in listTarget from ObjectExampleB.thirdAttr value
#Mapper(componentModel = "spring")
public interface ExampleMapper {
void populateThirdAttrInList(#MappingTarget List<ObjectExampleA> listTarget, ObjectExampleB objectExampleB);
}
Performing an update of elements of a collection is not always trivial. However, your case can be solved inn a simple way by doing an update of ObjectExampleA.
E.g.
#Mapper(componentModel = "spring")
public interface ExampleMapper {
default void populateThirdAttrInList(#MappingTarget List<ObjectExampleA> listTarget, ObjectExampleB objectExampleB) {
for(ObjectExampleA exampleA: listTarget) {
populateThirdAttr(exampleA, objectExampleB);
}
}
void populateThirdAttr(#MappingTarget ObjectExampleA exampleA, ObjectExampleB exampleB);
}
Related
Is it possible to cast List Objects to List of Objects from Factory pattern?
I have a Jersey REST endpoint and I migrate data from one environment to another. I wish to post some list of Object and cast them to right object taken from factory pattern
#Path("/migrateTableAtOnce")
#Consumes(MediaType.APPLICATION_JSON)
public <T> Response saveObjectIntoDb(List<T> listOfObj) {
// if listOfObj.getTableName() == "MW_ID_GENERATOR" tableOject gets new MwIdGenerator()
myEntity tableObject = myEntityFactory.getTable(listOfObj.getTableName());
return Response.status(201).entity("ok").build();
}
Is it possible that I have only one post method which that generic List. I have 20 objects which I need to transfer and I dont want to write 20 post methods :( I dont know how to do it exactly.
One of my method looks like that:
#POST
#Path("/migrateTableAtOnceMwIdGenerator")
#Consumes(MediaType.APPLICATION_JSON)
public Response saveObjectIntoDb(List<MwIdGenerator> listOfObj) {
Boolean result = false;
String dbResponse ="";
try {
dbResponse = obtainFacade().saveToDb(listOfObj);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return Response.status(201).entity(result+" "+dbResponse).build();
}
Is there no better solution to solve this problem?
I post the body as a custom object, and have a list within that object like;
#POST
#Path("/migrateTableAtOnceMwIdGenerator")
#Consumes(MediaType.APPLICATION_JSON)
public Response saveObjectIntoDb(CustomObject object) {
List <Stuff>list = object.getList();
and the object
public class CustomObject extends Serializable {
public List <Stuff>sList = null;
public List <OtherStuff>osList = null;
public List <TheBestStuff>tbsList = null; //etcetc
public List getList ()
{
return list;
}
public void setList(List <Stuff>list)
{
this.list = list;
}
public List getOsList ()
{
return osList ;
}
public void setList(List <OtherStuff>osList)
{
this.osList = osList;
}
public List getTbsList ()
{
return tbsList;
}
public void setTbsList(List <TheBestStuff>tbsList)
{
this.tbsList = tbsList;
}
and Jersey can parse the json object into your custom object, provided that you can pass the fields of that class as json. Seeing as you're passing the data with json, you're limited as to your implimentation as json only covers String, int, boolean and simple date, but you can pass most values as String and then parse.
I have a Switch that contains 13 case, each case executes a different sql request. I got the result in an ArrayList<HashMap<String, String>>. This result is supposed to be displayed with angular , for now i'm using this this.respTest = JSON.stringify(response); so it displays a list of "key":"value" .
My problem is since each request gets me different database fields and values ,so I want to merge some fields .
I created this class :
public class DataCollect {
private String type ;
private String entity ;
private String modPar ;
private String dateModif ;
private String numVersion ;
public DataCollect(String type, String entity, String modPar, String dateModif, String numVersion) {
this.type = type;
this.entity = entity;
this.modPar = modPar;
this.dateModif = dateModif;
this.numVersion = numVersion;
}
public DataCollect() {
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getEntity() {
return entity;
}
public void setEntity(String entity) {
this.entity = entity;
}
public String getModPar() {
return modPar;
}
public void setModPar(String modPar) {
this.modPar = modPar;
}
public String getDateModif() {
return dateModif;
}
public void setDateModif(String dateModif) {
this.dateModif = dateModif;
}
public String getNumVersion() {
return numVersion;
}
public void setNumVersion(String numVersion) {
this.numVersion = numVersion;
} }
In this class I'm supposed to affect the fields' names to the variables that I created and as a return an arraylist of hashmap with the data I extracted from the data base.
I mean I used to return for example "field-name":"value" , I want to return "type":"value","entity":"value" ..etc
I'm using springboot for the backend and angular 5 for the front.
Any help would be appreciated.
What you essentially want is a way to map keys in [each of] your hashmap to the corresponding member variable in the "DataCollect" POJO.
If there is a one to one mapping between the key present and corresponding member variable, you can expose a public constructor in "DataCollect" that takes in the hash map and constructs the corresponding object.
public DataCollect(Map<String, String> result) {
this.type = result.get("type");
this.entity = result.get("db_entity_key");
...
}
If there is no one on one mapping, you'd have to create a factory class, which takes your Map as an input and some context, and returns you the constructed DataCollect object.
Once you have the constructor or the factory class, you only need to iterate over your results list and do the needful to convert each Map into the DataCollect object.
Your controller should automatically serialise the DataCollect objects to corresponding JSON, or you can even use Jackson's ObjectMapper to achieve the same.
I want to create a ArrayList of data and return it via Rest point. I tried this:
#Service
public class CardBrandsListService {
public ArrayList<String> getCardBrandsList() {
ArrayList<String> list = new ArrayList<String>();
list.add("visa");
list.add("master");
list.add("Intl Maestro");
list.add("amex");
return list;
}
}
Rest endpoint:
#GetMapping("/card_brand/list")
public ResponseEntity<?> getCurruncy() {
return ResponseEntity.ok(cardBrandsListService.getCardBrandsList().entrySet().stream()
.map(g -> new CardBrandsListDTO(g.getValue())).collect(Collectors.toList()));
}
DTO:
public class CardBrandsListDTO {
private String card_brand;
public String getCard_brand() {
return card_brand;
}
public void setCard_brand(String card_brand) {
this.card_brand = card_brand;
}
}
But I get error: The method entrySet() is undefined for the type ArrayList<String> What is the proper wya to map ArrayList?
Your rest endpoint should look like the following:
#GetMapping("/card_brand/list")
public ResponseEntity<List<CardBrandsListDTO>> getCurruncy() {
return ResponseEntity.ok(cardBrandsListService.getCardBrandsList().stream()
.map(g -> new CardBrandsListDTO(g)).collect(Collectors.toList()));
You are calling entrySet(), which is used to get a Set of entries of a Map object (which you don't have). Additionally, inside the map function, your variable g is a String (since you are returning an ArrayList<String>), therefore you can directly supply that to the constructor. And you can directly set the correct type for the ResponseEntity as well.
UPDATE:
And you need the corresponding constructor:
public class CardBrandsListDTO {
private String card_brand;
public CarBrandsListDTO(String card_brand) {
this.car_brand = car_brand;
}
//getter and setter
}
By the way, I would advise you to rename the DTO (for understandability) and also the field inside it (to follow naming conventions)
I have a database call which possibly return null if none of criteria matched. If there is record match, the result is a Pojo which contains list of embedded object. I want to convert that Pojo into list of its embedded object id.
Foo.class has the list of Bars
public class Foo {
private List<Bar> bars;
//..setters & getters
}
Bar.class, I want to convert Foo into list of Bar's Id
public class Bar {
Integer id
//..setters & getters
}
I tired using Optional but it always returning into list of bars
Optional.ofNullable(fooRepo.search("some foo"))
.map(foo -> foo.getBars()); //How can turn this into list of Bar's Id
I'm not certain I understand your question but I'm interpreting it as:
A database query can return an object containing a list of references to another object, or null if no references are returned. How do I convert that object (or null) into a list of values from the referenced objects. I want an empty list if the query returned a null.
If I've got your question correct, then I suggest:
Optional<Foo> possibleFoo = Optional.ofNullable(dbQuery());
List<Integer> ids = possibleFoo
.map(f -> f.bars.stream()
.map(b -> b.id)
.collect(Collectors.toList()))
.orElse(Collections.EMPTY_LIST);
Here you go:
Optional.ofNullable(foo).map(Foo::getBars).map(y -> y.stream().map(z -> z.id).collect(Collectors.toList()))
Full tested code:
public class Test {
public static class Bar {
public Bar(Integer id) {
this.id = id;
}
Integer id;
}
public static class Foo {
private List<Bar> bars = new ArrayList<>();
public List<Bar> getBars() {
return bars;
}
}
public static void main(String[] argb) {
Foo nullFoo = null;
Optional<List<Integer>> nullList = convertToIdList(nullFoo);
System.out.println(nullList); // Optional.empty
Foo notNullFoo = new Foo();
notNullFoo.getBars().add(new Bar(3));
notNullFoo.getBars().add(new Bar(4));
notNullFoo.getBars().add(new Bar(5));
Optional<List<Integer>> notNullList = convertToIdList(notNullFoo);
System.out.println(notNullList); // Optional[[3, 4, 5]]
}
private static Optional<List<Integer>> convertToIdList(Foo foo) {
return Optional.ofNullable(foo).map(Foo::getBars).map(y -> y.stream().map(z -> z.id).collect(Collectors.toList()));
}
}
The key thing is to treat the list itself as an Optional, but if it is present to transform that single list from one element type to another. Please let me know if you have any questions.
I'm working on creating an API that has nested lists. Jackson seems like a great tool to create objects, but I can't quite figure out how to nest a list, and I'm wondering if its possible.
My object looks like this.
public class Order {
public String name;
public List<Item> items;
}
I'm hoping there is a way to map it to json that looks something like:
{
name : "A name"
items : {
elements : [{
price : 30
}]
}
}
We want to be able to do this so we can add properties to lists.
You can write custom deserializer for List<Item> items. See below example:
class ItemsJsonDeserializer extends JsonDeserializer<List<Item>> {
#Override
public List<Item> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
InnerItems innerItems = jp.readValueAs(InnerItems.class);
return innerItems.elements;
}
private static class InnerItems {
public List<Item> elements;
}
}
Now, you have to inform Jackson to use it for your property. You can do this in this way:
public class Order {
public String name;
#JsonDeserialize(using = ItemsJsonDeserializer.class)
public List<Item> items;
}
In general it is best to map JSON structure exactly to Java. In your case you could use something like:
public class Order {
public String name;
public ItemList items;
}
public class ItemList {
public List<Item> elements;
// and any properties you might want...
}
alternatively, you could probably also use (relatively) new #JsonFormat annotation:
public class Order {
public String name;
public ItemList items;
}
// annotation can be used on propery or class
#JsonFormat(shape=Shape.OBJECT) // instead of Shape.ARRAY
public class ItemList extends ArrayList<Item>
{
public Iterator<Item> getElements() { return this.iterator(); }
public String getSomeAttribute() { ... }
}
where you are forcing List or Collection to be serialized as if it was POJO, instead of normal special handling. There may be some side-effects, since introspection is used to find possible accessors, but the general approach should work
Your JSON translates to: "the object named items is of a type that has a property named elements which is a list of some sort".
So your Item class just needs an elements property:
class Item {
List<Something> getElements();
}
Note that your Java code doesn't map to your JSON. Your Java classes would map to something like:
{
"name" : "foo",
"items" : [
{ /* encoded version of Item */ }
]
}
For scala, one can try:
class ItemsJsonDeserializer extends JsonDeserializer[List[Item]] {
val mapper = new ObjectMapper() with ScalaObjectMapper
mapper.registerModule(DefaultScalaModule)
override def deserialize(jp: JsonParser, dc: DeserializationContext): List[Item] = {
val oc = jp.getCodec
val nodes = oc.readTree[ObjectNode](jp).get("elements").asScala.toList
val res = nodes.map { node =>
mapper.readValue[Item](node.toString)
}
res
}
}
case class Item(price: Int)
case class Order {
name: String,
#JsonDeserialize(using = classOf[ItemsJsonDeserializer])
items: List<Item>
}