Jackson JSON to pojo from array of objects with no property name - java

Considering this structure, what is the correct notation for getting the array of objects (property, type fields) inside of the parent property.
{"parent":
[
{"property":[2,5],"type":2},
{"property":[1,2],"type":1},
{"property":[4,0],"type":0}
],
"prop2":"something"
}
Currently the java looks like
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Parent{
<WHAT TO PUT HERE??>
List<PropertyTypeObj> propertyTypes;
}
This is part of something larger like:
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Container{
#JsonProperty("parent")
List<Parent> parent;
#JsonProperty("prop2")
String prop2
}
The solution was to bypass the parent element creation and instead use the PropertyTypeObject itself
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Container{
#JsonProperty("parent")
List<PropertyTypeObject> properties;
#JsonProperty("prop2")
String prop2
}
And then specify the PropertyTypeObject as having #JsonRootName("parent")
See approved answer for clarity.

A possible class structure is the following:
public class External {
private List<External.Internal> parent;
private String prop2;
#JsonRootName("parent")
public static class Internal {
private List<Integer> property;
private Integer type;
}
}
where the external class has:
a parent property that is a List (array in the json) of Inner elements
prop2 property of type String
and an internal class that has for each element:
a property property of type List (array in json) of integers
a type property of type integer

Related

Java Mapstruct generic enum converter

I have two different enum classes and one of them use them as a value like
public enum Type{
TEST1{
#Override
public Type convertToINT() {
return Type.INTEGRATION1;
}
},
TEST2{
#Override
public Type convertToINT() {
return Type.INTEGRATION2;
}
},
TEST3{
#Override
public TypeIntegration convertToINT(){
return Type.INTEGRATION3;
}
};
public abstract TypeIntegration convertToINT();
}
public enum TypeIntegration {
INTEGRATION1,
INTEGRATION2,
INTEGRATION3
}
This enums uses in different classes for example ;
#Getter
#Setter
public class typeSaveReqDto{
private blabla;
private blabla;
private Type type;
}
#Getter
#Setter
public class typeIntegrationObject{
private blabla;
private blabla
private TypeIntegration type;
}
I want to use mapstructs and convert via auto generated classes, but mapstruct throws me exception like "The following constants from the property "Type type" enum have no corresponding constant in the "TypeIntegration type" enum and must be be mapped via adding additional mappings: TEST1, TEST2, TEST3"
I want to create EnumMapper classes for converting enums, How can i write generic classes for this with mapStructs java ?
Edit :
I generated EnumMapper
#Mapper
public class EnumMapper {
EnumMapper INSTANCE = Mappers.getMapper(EnumMapper.class);
#Named("enumToIntEnum")
public static <T extends EnumConverter<INT>,INT> INT convertToINT(T enums, #TargetType INT enumClass){
INT convertObj = ((T)enums).convertToINT();
return convertObj;
}
}
And Mapper interfaces like below
#Mapper(componentModel = "spring",uses = EnumMapper.class)
public interface TypeReqMapper {
#Mapping(source = "type" , target = "type",qualifiedByName = "enumToIntEnum")
public TypeIntegrationObject typeSaveReqDtoTotypeIntegrationObject(TypeSaveReqDto typeSaveReqDto);
}
But I got a fail like 'Can't map property "Type type" to "TypeIntegration type". Consider to declare/implement a mapping method: "TypeIntegration map(Type value)".'
Type T isn't know and doesn't contain a convertToINT method as it can be anything. So keep it simple and just write a dedicated mapper instead of trying to build one that does everything.
#Mapper(componentModel="spring")
public class TypeToTypeIntegrationMapper {
#Mapping
public TypeIntegration map(Type from) {
return from.convertToINT();
}
}
Don't make it more complex.
You could even ditch the mapper and write an expression instead.
#Mapper(componentModel = "spring",uses = EnumMapper.class)
public interface TypeReqMapper {
#Mapping(source = "type" , target = "type", expression = "java(type.convertToINT())")
public TypeIntegrationObject typeSaveReqDtoTotypeIntegrationObject(TypeSaveReqDto typeSaveReqDto);
}
MapStruct will now use the expression to generate the mapping code instead of you having to write a mapper yourself.

JAXB unmarshalling based on element's value

I would like to unmarshall an object using JAXB based on the enum value/string present in the xml. I have several classes inheriting from one abstract class:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlSeeAlso({ InheritingClassOne.class, InheritingClassTwo.class })
public abstract class BasicClass {
protected String type; //determines class type
protected String description;
//getters & setters
}
two examplary subclasses:
#XmlRootElement(name = "someRoot")
#XmlAccessorType(XmlAccessType.FIELD)
public class InheritingClassOne extends BasicClass {
private String message;
private Float mark;
//getters & setters
}
#XmlRootElement(name = "someRoot")
#XmlAccessorType(XmlAccessType.FIELD)
public class InheritingClassTwo extends BasicClass {
private Integer value;
//getters & setters
}
I know that JAXB can unmarshall objects based on xsi:type attribute, which I cannot use, since the input xml is stripped from all atributes. I have tried using Moxy #XmlDiscriminatorNode & #XmlDiscriminatorValue, but these seem to work only with attributes and not the element values.
I have also seen #XmlElementRef which lets determine the type based on the name of the element, but again, due to some restrictions all elements have to have the same name in input and output xml.
My input xml is:
<someRoot>
<type>chooseOne</type>
<message>Message for InheritingClassOne</message>
<mark>12.3</mark>
</someRoot>
I did not find solution for this problem other than using #XmlJavaAdapter with defined adapter:
public class CustomAdapter extends XmlAdapter<Object, BasicClass> {
#Override
public BasicClass unmarshal(Object v) throws Exception {
//TODO: cast v to Element interface, get to type element value and handle accordingly
return null;
}
#Override
public Object marshal(BasicClass v) throws Exception {
//TODO: marshal
return null;
}
}
The adapter solution with reading ElementNsImpl child values to get the category seems awful and takes a lot of effort for such task. Are there any solutions that I am missing? Can I somehow change my models (without using xml attributes), so this task is doable?

How i can map enum class to attributes from other object?

I have two classes, one of them is a map with name and position of a tabbed file:
public enum fieldPosition {
field_1(0),
field_2(1),
// other fields
}
The other is a simple entity:
public class simpleEntiy {
private String name;
private String desc;
// other attributes
}
I want to generate a tabbed file based on position of enum class, but using the object from entity class with spring annotations. Its possible?
Is there some way to use map on entity class to mapper the enum class?
For example:
public class simpleEntiy {
//some annotation to field_1 or position 0
private String name;
//some annotation to field_2 or position 1
private String desc;
// other attributes
}
I'm using java 8 and spring boot 1.4.3.
Thanks

How do you send back a subset of a JPA entity that is owned by another entity?

I have an entity that owns another entity:
//psuedocode
public class ClassA{
private String name;
#OneToOne
private ClassB classb;
}
public class ClassB{
private String thing1;
private String thing2;
private String thing3;
}
When I retrieve ClassA objects, I don't want to see ClassB.thing3, but I do want to see thing1 and thing 2:
{
"name":"classa",
"classb":{
"thing1":"hi",
"thing2":"there"
}
}
But if I query for ClassB I want to see everything:
{"thing1":"hi",
"thing2":"there",
"thing3":"joseph"}
So I can't just put an ignore annotation over thing3, because then I'll ignore it on the second fetch. I tried a Converter<ClassB>, but that forces me to implement toString() and fromString() for the JSON, which dies on converting the JSON object to Java-side (the converter expects a String, but gets the object instead).
I want to avoid building/parsing the JSON object myself if possible to let my json provider do the work, if possible. I'm on Johnzon.
This is possible, you need to use #NamedEntityGraph,
This should help, http://www.thoughts-on-java.org/jpa-21-entity-graph-part-1-named-entity/
Something like this should be possible by querying using SELECT NEW, but you're going to need some new Classes for that ... and won't be passing your entities directly to JSON.
new Classes:
(pseudocode)
class ResultB {
String thing1;
String thing2;
public ResultB(ClassB classB) {
this.thing1 = classB.thing1;
this.thing2 = classB.thing2;
}
}
class ResultA {
String name;
ResultB resultB;
public ResultA(ClassA classA) {
this.name=classA.name;
this.resultB=new ResultB(classA);
}
}
Query:
select new ResultA(a) from ClassA a fetch join a.classB;
Then you can pass ResultA instead of ClassA to JSON.
PS: As mentioned in the comment above, I don't think NamedEntityGraphs are the way to go here
I would always fetch all the data from the database and let the filtering to be done by the JSON provider if you want to serialize it anyway. If you use Jackson you can simply add views to your fields:
public class ClassA {
#JsonView(Views.AlwaysInclude.class)
private String name;
#JsonView(Views.AlwaysInclude.class)
#OneToOne
private ClassB classb;
}
public class ClassB {
#JsonView(Views.AlwaysInclude.class)
private String thing1;
#JsonView(Views.AlwaysInclude.class)
private String thing2;
private String thing3;
}
public class Views {
public static class AlwaysInclude {
}
}
Later when you serialize your object you just need to use your view:
String result = mapper
.writerWithView(Views.AlwaysInclude.class)
.writeValueAsString(new ClassA());
When you want to serialize only ClassB then you shouldn't use views.
String result = mapper.writeValueAsString(new ClassB());

How to write the JAXB object that has attribute and value

Here's my intended XML structure
<Outer type="good" id="1">
<Uid>123</Uid>
<Name>Myself</Name>
<Inner type="bad">This Value</Inner>
</Outer>
Here's my Object.
#XmlAccessorType(XMLAccessType.FIELD)
#XmlType(name="Outer", propOrder = {
"uid"
"name"
"inner"
})
public class Outer{
#XmlElement(name = "Uid")
protected String uid;
#XmlElement(name = "Name")
protected String name;
#XmlElement(name = "Inner")
protected Inner inner;
public static class Inner{
#XmlAttribute
private String type;
#XmlValue
private String value;
//setters & getters for both
}
//setters & getters for all the elements
}
Now in my class I am doing
Outer o = new Outer();
o.setUid/ID/Type/Name() ; //all the setter
Inner i - new Inner();
i.setValue("This Value");
i.setType("bad");
When Irun this i am getting
If a class has #XmlElement property, it cannot have #XmlValue property.
And
Class has two properties of the same name "type" (This one is for the Source class)
And
Class has two properties of the same name "value" (This one is for Source class too)
What is happening, and what I can I do rectify this?
Thanks
Currently, JAXB threats both fields (due to annotations) and both pairs of get/set (due to default accessor type) as properties. So you class Inner has 4 properties.
Please, add own accessor type for Inner class
#XmlAccessorType(XmlAccessType.FIELD)
public static class Inner
{
Or annotate properties instead of fields
public static class Inner
{
private String type;
private String value;
#XmlAttribute
public String getType()
{
return type;
}
// setter setType
#XmlValue
public String getValue()
{
return value;
}
// setter setValue
}
Add XmlRootElement annotation to the Outer class, besides of that it shoud work.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "Outer", propOrder = {"uid", "name", "inner"})
public static class Outer {

Categories