JSON Objectmapper issue - java

Getting both java obejct as will jsonproperty is getting generated whilc I convert java object to JSON.
Can you please confirm where I have made mistake.

Add #JsonAutoDetect(getterVisibility= JsonAutoDetect.Visibility.NONE) to your class:
#JsonAutoDetect(getterVisibility= JsonAutoDetect.Visibility.NONE)
#JsonInclude(JsonInclude.Include.NON_EMPTY)
public class FalconidePersonalizationVO {
By default Jackson follow java bean convention to output json properties. As result, it founds your getX method and output xapiheader property.
But you also annotate your field with #JsonProperty so another property named x-apiheader is also ouputed.
Disable getterX detection method will prevent jackson output getter fields.

**************** Solution 1 ****************
Annotate getter / setter with #JsonProperty as well (now annotating field is not mandatory)
public class FalconidePersonalizationVO {
#JsonProperty("x-apiheader-cc")
private String xApiheaderCc;
#JsonProperty("x-apiheader")
private String xApiheader;
#JsonProperty("x-apiheader-cc")
public String getXApiheaderCc() {
return xApiheaderCc;
}
#JsonProperty("x-apiheader-cc")
public void setXApiheaderCc(String xApiheaderCc) {
this.xApiheaderCc = xApiheaderCc;
}
#JsonProperty("x-apiheader")
public String getXApiheader() {
return xApiheader;
}
#JsonProperty("x-apiheader")
public void setXApiheader(String xApiheader) {
this.xApiheader = xApiheader;
}
}
**************** Solution 2 ****************
Follow setter / getter naming convention. In normal naming convention first letter of field name is capitalized prepending it with set / get. But in this case since second char is capital so, first char is not capitalized. See https://stackoverflow.com/a/16146215/3295987
public class FalconidePersonalizationVO {
#JsonProperty("x-apiheader-cc")
private String xApiheaderCc;
#JsonProperty("x-apiheader")
private String xApiheader;
/*
* Setter / getter auto generated in eclipse
*/
// getXApiheaderCc -> getxApiheaderCc
public String getxApiheaderCc() {
return xApiheaderCc;
}
public void setxApiheaderCc(String xApiheaderCc) {
this.xApiheaderCc = xApiheaderCc;
}
public String getxApiheader() {
return xApiheader;
}
public void setxApiheader(String xApiheader) {
this.xApiheader = xApiheader;
}
}

Related

Is it possible to create enums with a variable which is defined only when using this enum?

I am trying to build an object which will be used to communicate with other objects. This communication object should have an enum, these enums include "ORDER_CREATED", "ORDER_CANCELLED" and "ORDER_AT_LOCATION". What I now want to do is assign a value to the enum "ORDER_AT_LOCATION" with a String location. This way there are no blank fields containing "null" if the enum is "ORDER_CREATED".
I am not entirely sure if this is even possible.
I tried using a constructor for one specific enum but didn't have any luck
public class OrderEvent {
private OrderEventTypes eventType;
}
enum OrderEventTypes{
//I want a constructor with String info only for the enum ORDER_AT_LOCATION
ORDER_AT_LOCATION{
String info;
public void ORDER_IN_TRANSIT(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
}
, ORDER_CANCELLED, ORDER_COMPLETED, ORDER_CREATED;
}
the expected result should be that this statement works.
if(eventType.equals("ORDER_AT_LOCATION")) {
System.out.println(eventType.getInfo());
}
if you have any other nice solutions to this I would be very thankful, all the solutions I could come up with were perfectly do-able but not as nice as this would be.
You can create the enum with a constructor which accepts a String value and initialises the info field:
enum OrderEventTypes{
ORDER_AT_LOCATION("ORDER_AT_LOCATION"),
ORDER_CANCELLED,
ORDER_COMPLETED,
ORDER_CREATED;
private final String info;
OrderEventTypes(){
this("");
}
OrderEventTypes(String info){
this.info = info;
}
public String getInfo(){
return this.info;
}
#Override
public String toString() {
return this.info;
}
}
Now when you need to compare, you can use the getter to get the value of the info field:
if("ORDER_AT_LOCATION".equals(eventType.getInfo())){
System.out.println(eventType.getInfo());
}

can't response 'isOk' field in spring boot

i'm creating CreateOrUpdateProduct API use Spring boot. i want to return to consumer two fields ('message & isOk'). But when i exec this API, i received ('message & ok') fields. what's happened? please expand me. thanks advance!
this is my function
public ResponseBase CreateOrUpdateProduct(Product product) {
....
return responseBase;
}
public class ResponseBase {
boolean isOk;
public boolean isOk() {
return isOk;
}
public void setOk(boolean isOk) {
this.isOk = isOk;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
String message;
}
i received
{
"message":null,
"ok": true
}
I think your answer is here: Jackson renames boolean field by removing is
Jackson (serializer) sees "isOk" as a get method of a boolean variable named "ok". This is a common naming pattern developers use on get methods for boolean variables.
EDIT:
You shouldn't set the name of your method to "getIsOk", because that doesn't follow the naming convention of get method for boolean variables. This is not a very good solution, but it'll work.
Jackson provides an annotation to you that set the name of the serialized variable:
#JsonProperty(value="isOk")
public boolean isOk() {
return isOk;
}
You should rename your getter to getIsOk().
It will return the expected answer :
{
"message":null,
"isOk": true
}

Copy data to same classes in different packages

I am calling an external service that returns the following class:
package abc;
public class FirstClass {
private String name;
private String age;
private String number;
}
In my model, I have defined a class with same structure:
package xyz;
public class FirstClass {
private String name;
private String age;
private String number;
}
I want to copy data from the abc.FirstClass object to xyz.FirstClass object. I don't want to map the data field by field. I think it can be done by dozer - are there any easier methods to do it?
You could use PropertyUtils#copyProperties:
Copy property values from the "origin" bean to the "destination" bean for all cases where the property names are the same (even though the actual getter and setter methods might have been customized via BeanInfo classes).
Example:
abc.FirstClass src = new abc.FirstClass();
xyz.FirstClass dest = new xyz.FirstClass();
PropertyUtils.copyProperties(dest, src);
The reason you cannot copy the entire class object is because each class object has unique hashcode. Even if your class has same attribute.
I know it is a pain but mapping by field is the only way to go.
You can try use spring beans to help map the fields.
Java Reflection is the way to go.
From The Java™ Tutorials
A field is a class, interface, or enum with an associated value. Methods in the java.lang.reflect.Field class can retrieve information about the field, such as its name, type, modifiers, and annotations. There are also methods which enable dynamic access and modification of the value of the field
Try something like this:
StackOverflow.abc.firstClass abc = new StackOverflow.abc.firstClass();
StackOverflow.xyz.firstClass xyz = new StackOverflow.xyz.firstClass();
Class<? extends StackOverflow.xyz.firstClass> xyzClass = xyz.getClass();
Field[] fields = abc.getClass().getDeclaredFields();
for (Field abcField : fields) {
abcField.setAccessible(true); //To access private fields
try {
Field xyzField = xyzClass.getDeclaredField(abcField.getName());
xyzField.setAccessible(true);
xyzField.set(xyz, abcField.get(abc));
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
You can check out this tutorial from Oracle for more details. Or, specifically this page from the tutorial.
You can using reflection
this does the job and shows it:
public class FirstClass {
private String name;
private String age;
private String number;
public FirstClass(String _name, String _age, String _number)
{
name=_name; age=_age; number=_number;
}
}
public class CloneClass {
private String name;
private String age;
private String number;
public CloneClass(String _name, String _age, String _number)
{
name=_name; age=_age; number=_number;
}
public void show()
{
System.out.println("NAME="+name+" AGE="+age+" NUMBER="+number);
}
}
FirstClass A=new FirstClass("Jules","44","123A4535");
CloneClass B=new CloneClass("","","");
Class class1=A.getClass();
Class class2=B.getClass();
// all fields from A
Field[] fields_A = class1.getDeclaredFields();
Field[] fields_B = class2.getDeclaredFields();
for (int k=0;k<fields_A.length;k++)
{
Field one_field=fields_A[k];
// Name of field in source
String name_of_field=one_field.getName();
if (name_of_field.equals("this$0")) continue; // Not this !
// Search if it exists in destination
for (int z=0;z<fields_B.length;z++)
{
Field field_destination=fields_B[k];
String name_of_field2=field_destination.getName();
if (name_of_field.equals(name_of_field2))
// TODO
// You should also verify the type !
{
try
{
// To read private var
one_field.setAccessible(true);
field_destination.setAccessible(true);
Object value=one_field.get( A);
field_destination.set(B, value);
}
catch (Exception ex) {System.err.println(ex);}
}
}
} // for (int k=0;k<fields_A.length;k++)
B.show();

Java enum error - return type reqiued

I created simple enum class in java.
public enum XmlElementsInput {
element_sentenceInput("a");
element_sentence("b");
private final String elementName;
private XmlElementsInput(String name) {
this.elementName = name;
}
public String getElementName() {
return elementName;
}
}
But Netbeans say me: invalid method declaration; return type required, ilegal start of type on line element_sentence("b");. I dont know why? Can you tell me why?
The enum types must separated by comma:
element_sentenceInput("a"),
element_sentence("b");
Use commas to separate enum values, as follows:
public enum XmlElementsInput {
element_sentenceInput("a"),
element_sentence("b");
// Remaining part
}

Jaxb, Class has two properties of the same name

With Jaxb (jaxb-impl-2.1.12), UI try to read an XML file
Only a few element in the XML file are interesting, so I would like to skip most of the elements.
The XML I'm trying to read:
<?xml version="1.0" encoding="UTF-8"?>
<!--Sample XML file generated by XMLSpy v2010 rel. 3 sp1 (http://www.altova.com)-->
<flx:ModeleREP xsi:schemaLocation="urn:test:mod_rep.xsd mod_rep.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flx="urn:test:mod_rep.xsd">
<flx:DocumentHeader>
<flx:Identification v="04489"/>
</flx:DocumentHeader>
<flx:TimeSeries>
<flx:Identification v="test1a"/>
<flx:BusinessType v="A01"/>
<flx:Product v="123a"/>
<flx:ResourceObject codingScheme="N" v="testa"/>
<flx:Period>
<flx:TimeInterval v="2011-07-02T00:00/2011-07-16T00:00"/>
<flx:Resolution v="PT2H"/>
<flx:Pt>
<flx:P v="1"/>
<flx:Q unitCode="String" v="1.0"/>
<flx:A currencyIdentifier="String" v="195.0"/>
</flx:Pt>
</flx:Period>
</flx:TimeSeries>
<flx:TimeSeries>
<flx:Identification v="test2a"/>
<flx:BusinessType v="A01"/>
<flx:Product v="a123b"/>
<flx:ResourceObject codingScheme="N" v="test2"/>
<flx:Period>
<flx:TimeInterval v="2011-07-02T00:00/2011-07-16T00:00"/>
<flx:Resolution v="PT2H"/>
<flx:Pt>
<flx:P v="1"/>
<flx:Q unitCode="String" v="1.0"/>
<flx:A currencyIdentifier="String" v="195.0"/>
</flx:Pt>
<flx:Pt>
<flx:P v="2"/>
<flx:Q unitCode="String" v="1.0"/>
<flx:A currencyIdentifier="String" v="195.0"/>
</flx:Pt>
</flx:Period>
</flx:TimeSeries>
</flx:ModeleREP>
my class
#XmlRootElement(name="ModeleREP", namespace="urn:test:mod_rep.xsd")
public class ModeleREP {
#XmlElement(name="TimeSeries")
protected List<TimeSeries> timeSeries;
public List<TimeSeries> getTimeSeries() {
if (this.timeSeries == null) {
this.timeSeries = new ArrayList<TimeSeries>();
}
return this.timeSeries;
}
public void setTimeSeries(List<TimeSeries> timeSeries) {
this.timeSeries = timeSeries;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "TimeSeries")
public class TimeSeries {
#XmlElement(name="ResourceObject")
protected RessourceObject resourceObject;
#XmlElement(name = "Period")
protected Period period;
public RessourceObject getResourceObject() {
return this.resourceObject;
}
public void setResourceObject(RessourceObject resourceObject) {
this.resourceObject = resourceObject;
}
public Period getPeriod() {
return this.period;
}
public void setPeriod(Period period) {
this.period = period;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "ResourceObject")
public class RessourceObject {
#XmlAttribute(name = "codingScheme")
protected String codingScheme;
#XmlAttribute(name = "v")
protected String v;
public String getCodingScheme() {
return this.codingScheme;
}
public void setCodingScheme(String codingScheme) {
this.codingScheme = codingScheme;
}
public String getV() {
return this.v;
}
public void setV(String v) {
this.v = v;
}
}
#XmlAccessorType(XmlAccessType.NONE)
#XmlRootElement(name = "Period")
public class Period {
#XmlElement(name = "TimeInterval")
protected TimeInterval timeInterval;
#XmlElement(name = "Pt")
protected List<Pt> pt;
public TimeInterval getTimeInterval() {
return this.timeInterval;
}
public void setTimeInterval(TimeInterval timeInterval) {
this.timeInterval = timeInterval;
}
public List<Pt> getPt() {
if (this.pt == null) {
this.pt = new ArrayList<Pt>();
}
return this.pt;
}
public void setPt(List<Pt> pt) {
this.pt=pt;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "TimeInterval")
public class TimeInterval {
#XmlAttribute(name = "v")
private String timeIntervalPeriod;
public String getTimeIntervalPeriod() {
return this.timeIntervalPeriod;
}
public void setTimeIntervalPeriod(String timeIntervalPeriod) {
this.timeIntervalPeriod = timeIntervalPeriod;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "Pt")
public class Pt {
#XmlElement(name = "P")
protected P p;
#XmlElement(name = "A")
protected A a;
public P getP() {
return this.p;
}
public void setP(P p) {
this.p = p;
}
public A getA() {
return this.a;
}
public void setA(A a) {
this.a = a;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "P")
public class P {
#XmlAttribute(name = "v")
protected String position;
public String getPosition(){
return this.position;
}
public void setPosition(String position){
this.position=position;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "A")
public class A {
#XmlAttribute(name = "v")
protected String calculatedAmount;
public String getCalculatedAmount() {
return this.calculatedAmount;
}
public void setCalculatedAmount(String calculatedAmount) {
this.calculatedAmount = calculatedAmount;
}
}
when I try to read the XML file, I get this error:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "timeSeries"
this problem is related to the following location:
at public java.util.List testjaxp.ModeleREP.getTimeSeries()
at testjaxp.ModeleREP
this problem is related to the following location:
at protected java.util.List testjaxp.ModeleREP.timeSeries
at testjaxp.ModeleREP
I don't understand this error. And sometimes when I check my object, timeSeries is null.
How can I fix this error/prevent timeSeries from returning null?
I set these properties when I faced this problem. Setting one or both of them may solve your issue:
#XmlRootElement(name="yourRootElementName")
#XmlAccessorType(XmlAccessType.FIELD)
There are multiple solutions: If you annotate on variable declaration then you need #XmlAccessorType(XmlAccessType.FIELD), but if you prefer to annotate either a get- or set-method then you don't.
So you can do:
#XmlRootElement(name="MY_CLASS_A")
#XmlAccessorType(XmlAccessType.FIELD)
public class MyClassA
{
#XmlElement(name = "STATUS")
private int status;
//.. and so on
}
Or:
#XmlRootElement(name="MY_CLASS_A")
public class MyClassA
{
private int status;
#XmlElement(name = "STATUS")
public int getStatus()
{
}
}
You didn't specified what JAXB-IMPL version are you using, but once I had the same problem (with jaxb-impl 2.0.5) and solved it using the annotation at the getter level instead of using it at the member level.
I've also seen some similiar issues like this.
I think, it's because of the place where we use the "#XMLElement" annotation in the (bean) class.
And I think, the JAXB (annotation processor) considers the member field & getter method of the same field element as different properties, when we use the #XMLElement annotation at the field level and throws the IllegalAnnotationExceptions exception.
Exception Message :
Class has two properties of the same name "timeSeries"
At Getter Method :
at public java.util.List testjaxp.ModeleREP.getTimeSeries()
At Member Field :
at protected java.util.List testjaxp.ModeleREP.timeSeries
Solution :
Instead of using #XmlElement in the field, use it in the getter method.
just added this to my class
#XmlAccessorType(XmlAccessType.FIELD)
worked like a cham
Your JAXB is looking at both the getTimeSeries() method and the member timeSeries. You don't say which JAXB implementation you're using, or its configuration, but the exception is fairly clear.
at public java.util.List testjaxp.ModeleREP.getTimeSeries()
and
at protected java.util.List testjaxp.ModeleREP.timeSeries
You need to configure you JAXB stuff to use annotations (as per your #XmlElement(name="TimeSeries")) and ignore public methods.
If we use the below annotations and remove the "#XmlElement" annotation, code should work properly and resultant XML would have the element names similar to the class member.
#XmlRootElement(name="<RootElementName>")
#XmlAccessorType(XmlAccessType.FIELD)
In case use of "#XmlElement" is really required, please define it as field level and code should work perfectly. Don't define the annotation on the top of getter method.
Had tried both the above approaches mentioned and got to fix the issue.
You need to configure class ModeleREP as well with #XmlAccessorType(XmlAccessType.FIELD) as you did with class TimeSeries.
Have al look at OOXS
"Class has two properties of the same name exception" can happen when you have a class member x with a public access level and a getter/setter for the same member.
As a java rule of thumb, it is not recommended to use a public access level together with getters and setters.
Check this for more details:
Public property VS Private property with getter?
To fix that:
Change your member's access level to private and keep your getter/setter
Remove the member's getter and setter
These are the two properties JAXB is looking at.
public java.util.List testjaxp.ModeleREP.getTimeSeries()
and
protected java.util.List testjaxp.ModeleREP.timeSeries
This can be avoided by using JAXB annotation at get method just like mentioned below.
#XmlElement(name="TimeSeries"))
public java.util.List testjaxp.ModeleREP.getTimeSeries()
Declare the member variables to private in the class you want to convert to XML.
It will work when you put your annotation before the getters, and remove it from the protected attributes:
protected String codingScheme;
#XmlAttribute(name = "codingScheme")
public String getCodingScheme() {
return this.codingScheme;
}
The source of the problem is that you have both XmlAccessType.FIELD and pairs of getters and setters. The solution is to remove setters and add a default constructor and a constructor that takes all fields.
ModeleREP#getTimeSeries() have to be with #Transient annotation. That would help.
I had a service class with a signature as below:
#WebMethod
public FetchIQAStatusResponseVO fetchIQAStatus(FetchIQAStatusRequest fetchIQAStatusRequest) {
On run I got the same error for FetchIQAStatusResponseVO fields. I just added a line on top of FetchIQAStatusResponseVO:
#XmlAccessorType(XmlAccessType.FIELD) //This line added
public class FetchIQAStatusResponseVO {
and this resolved the issue.
Annotating with #XmlTransient resolves that issue
#XmlTransient
public void setTimeSeries(List<TimeSeries> timeSeries) {
this.timeSeries = timeSeries;
}
Look at http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html for more details
Many solutions have been given, and the internals are briefly touched by #Sriram and #ptomli as well. I just want to add a few references to the source code to help understand what is happening under the hood.
By default (i.e. no extra annotations used at all except #XmlRootElement on the root class), JABX tries to marshal things exposed via two ways:
public fields
getter methods that are named following the convention and have a corresponding setter method.
Notice that if a field is (or method returns) null, it will not be written into the output.
Now if #XmlElement is used, non-public things (could be fields or getter methods) can be marshalled as well.
But the two ways, i.e. fields and getter-methods, must not conflict with each other. Otherwise you get the exception.
A quick and simple way to fix this issue is to remove the #XmlElement(name="TimeSeries") from the top of the variable declaration statement protected List<TimeSeries> timeSeries; to the top of its getter, public List<TimeSeries> getTimeSeries().
Thus your ModeleREP class will look like:
#XmlRootElement(name="ModeleREP", namespace="urn:test:mod_rep.xsd")
public class ModeleREP {
protected List<TimeSeries> timeSeries;
#XmlElement(name="TimeSeries")
public List<TimeSeries> getTimeSeries() {
if (this.timeSeries == null) {
this.timeSeries = new ArrayList<TimeSeries>();
}
return this.timeSeries;
}
public void setTimeSeries(List<TimeSeries> timeSeries) {
this.timeSeries = timeSeries;
}
}
I did trial and error and got the conclusion that, you only have to use either of both #XMLElement or #XmlAccessorType(XmlAccessType.FIELD).
When to use which?
case 1 : If your field names and element name you want to use in xml file are different then you have to use #XMLElement(name="elementName"). As this will bind fields with that element name and display in XML file.
case 2 : If fields names and respective element name in xml both are same then you can simply use #XmlAccessorType(XmlAccessType.FIELD)

Categories