Jackson ObjectMapper upper/lower case issues - java

When I serialize/deserialize any object, all field names are converted to lower case.
Is there any configuration to set that makes Jackson keep the field names exactly as they are? Both for serializing and deserializing?
(I know about #JsonProperty, but this does not seems to be right, since what I need is just for Jackson to respect what already exists)
My test code:
import java.io.Serializable;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
public class Test {
static class Example implements Serializable {
private String Test;
private String ABC;
private String XyZ;
public String getTest() { return Test; }
public void setTest(String test) { Test = test; }
public String getABC() { return ABC; }
public void setABC(String abc) { ABC = abc; }
public String getXyZ() { return XyZ; }
public void setXyZ(String xyz) { XyZ = xyz; }
}
static class MyPropertyNamingStrategy extends PropertyNamingStrategy {
#Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return convert(defaultName);
}
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(defaultName);
}
#Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(defaultName);
}
private String convert(String input) {
return input;
}
}
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper()
.setPropertyNamingStrategy(new MyPropertyNamingStrategy())
.enable(SerializationFeature.INDENT_OUTPUT)
.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
//From OBJECT to JSON
Example ex = new Example();
ex.setTest("1");
ex.setABC("2");
ex.setXyZ("3");
System.out.println(objectMapper.writeValueAsString(ex));
//FROM JSON to OBJECT
String jsonString = "{ \"Test\":\"0\", \"ABC\":\"1\", \"XyZ\":\"2\" }";
Example fEx = objectMapper.readValue(jsonString, Example.class);
}
}
Thanks to #BlueLettuce16, I have managed to build an 'improved' version of the PropertyNamingStrategy. Here it is:
import java.lang.reflect.Modifier;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
public class CustomPropertyNamingStrategy extends PropertyNamingStrategy {
#Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return convertForField(defaultName);
}
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convertForMethod(method, defaultName);
}
#Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convertForMethod(method, defaultName);
}
private String convertForField(String defaultName) {
return defaultName;
}
private String convertForMethod(AnnotatedMethod method, String defaultName) {
if (isGetter(method)) {
return method.getName().substring(3);
}
if (isSetter(method)) {
return method.getName().substring(3);
}
return defaultName;
}
private boolean isGetter(AnnotatedMethod method) {
if (Modifier.isPublic(method.getModifiers()) && method.getGenericParameterTypes().length == 0) {
if (method.getName().matches("^get[A-Z].*") && !method.getGenericReturnType().equals(void.class))
return true;
if (method.getName().matches("^is[A-Z].*") && method.getGenericReturnType().equals(boolean.class))
return true;
}
return false;
}
private boolean isSetter(AnnotatedMethod method) {
return Modifier.isPublic(method.getModifiers()) && method.getGenericReturnType().equals(void.class) && method.getGenericParameterTypes().length == 1
&& method.getName().matches("^set[A-Z].*");
}
}

Even though #JsonProperty doesn't work, I was able to use #JsonSetter and #JsonGetter to map capitalized json field names.
#JsonSetter("ABC")
public void setABC(String ABC) {
this.ABC= ABC;
}
Spring will now serialize the object field as "ABC" and not "abc".

I've had the same problem.
This is my solution:
public class MyNamingStrategy extends PropertyNamingStrategy {
#Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return field.getName();
}
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method, defaultName);
}
#Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method, defaultName);
}
private String convert(AnnotatedMethod method, String defaultName) {
Class<?> clazz = method.getDeclaringClass();
List<Field> flds = FieldUtils.getAllFieldsList(clazz);
for (Field fld : flds) {
if (fld.getName().equalsIgnoreCase(defaultName)) {
return fld.getName();
}
}
return defaultName;
}
}
In this case you will get the exact name of the property, and will not have to depend on the correct names of the methods.

I think that this is the solution (using custom PropertyNamingStrategy):
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
public class MyPropertyNamingStrategy extends PropertyNamingStrategy {
#Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return convert(field.getName());
}
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method.getName().toString());
}
#Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method.getName().toString());
}
private String convert(String input) {
return input.substring(3);
}
}
Test
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.IOException;
import java.io.StringWriter;
public class MyPropertyNamingStrategyTest {
public static void main(String[] args) {
PrivatePerson privatePerson = new PrivatePerson();
privatePerson.setFirstName("John");
privatePerson.setLastName("Smith");
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyPropertyNamingStrategy());
mapper.enable(SerializationFeature.INDENT_OUTPUT);
StringWriter sw = new StringWriter();
try {
mapper.writeValue(sw, privatePerson);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(sw.toString());
}
}
PrivatePerson
public class PrivatePerson {
private String firstName;
private String lastName;
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getLastName() {
return lastName;
}
}

You can configure Jackson to be case sensitivity tolerant:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
Cudos to https://stackoverflow.com/a/32842962/1639556

Using #JsonProperty annotation. It work well
Example
#JsonProperty("Code")
private String Code;
#JsonProperty("Message")
private String Message;

Created a own class for PropertyNamingStrategy- As per Answer 7 Working fine
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
public class MyPropertyNamingStrategy extends PropertyNamingStrategy {
#Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
return convert(field.getName());
}
#Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method.getName().toString());
}
#Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return convert(method.getName().toString());
}
private String convert(String input) {
return input.substring(3);
}
}
And I have my POJO class - the Payload Class:
package orderCreateAPI;
import java.util.ArrayList;
public class Payload {
OrderInfo OrderInfo;
ArrayList<orderCreateAPI.ShipmentInfo> ShipmentInfo;
public Payload(OrderInfo order, ArrayList<orderCreateAPI.ShipmentInfo> shipInfo){
this.OrderInfo =order;
this.ShipmentInfo = shipInfo;
}
public OrderInfo getOrderInfo() {
return OrderInfo;
}
public void setOrderInfo(OrderInfo orderInfo) {
OrderInfo = orderInfo;
}
public ArrayList<orderCreateAPI.ShipmentInfo> getShipmentInfo() {
return ShipmentInfo;
}
public void setShipmentInfo(ArrayList<orderCreateAPI.ShipmentInfo> shipmentInfo) {
ShipmentInfo = shipmentInfo;
}
}
The execution class:
public class TC1_CreateOrder extends orderCreateRequest{
#Test
public static void TC1_CreateOrder() throws JsonProcessingException,JsonMappingException,IOException {
//throws JsonParseException,JsonMappingException,IOException
//Data fetch
ArrayList<OrderReferences> orRef = new ArrayList<OrderReferences>();
orRef.add(new OrderReferences("BM","IFC"));
ArrayList<OrderItem> orItem = new ArrayList<OrderItem>();
orItem.add(new OrderItem("AOTEST1001","60111"));
ShipperInfo ship = new ShipperInfo("URBN","URBN PA DC");
ArrayList<ShipmentInfo> ShipInfo = new ArrayList<ShipmentInfo>();
ShipInfo.add(new ShipmentInfo("ASTEST1001","RCVD"),ship, orItem));
ConsigneeInfo ConsigneeInfo = new ConsigneeInfo("Green Mile","133 Avenue");
OrderInfo OrderInfo = new OrderInfo("AOTEST1001", "2021-09-03T",orRef, ConsigneeInfo);
Payload p = new Payload(OrderInfo,ShipInfo);
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyPropertyNamingStrategy());
StringWriter s = new StringWriter();
try {
mapper.writeValue(s, p);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Response body before: -Wrong properties
{
"orderInfo": {
"orderNumber": "AOTEST1010",
"orderCreatedDate": "2021-09-03T00:00:00.000Z"
}
}
Response body after: -correct properties
{
"OrderInfo": {
"OrderNumber": "AOTEST1010",
"OrderCreatedDate": "2021-09-03T00:00:00.000Z"
}
}

Related

Can Jackson automatically treat any constructor parameter as a JsonProperty?

How do I get Jackson to treat 'name' as if it had a #JsonProperty annotation?
public class SimpleClass {
private String name;
private String doNotSerialize;
public SimpleClass( #JsonProperty("name") String name ) {
this.name = name;
}
public String getName() {
return name;
}
public int getSum() {
return 1+1;
}
}
The way it is now, I get an error, Unrecognized field "sum", because it treats every getter as a serializable property.
If I add a class annotation:
#JsonAutoDetect( getterVisibility = JsonAutoDetect.Visibility.NONE )
I get an empty string when serializing. I was hoping that Jackson would see the #JsonProperty on the constructor parameter and figure it out.
If I change the class annotation to:
#JsonAutoDetect( getterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.ANY )
Then I get the 'doNotSerialize' field included.
If I set a #JsonCreator on the constructor, and change my autodetect, I still get a blank string:
#JsonAutoDetect( getterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY )
public class SimpleClass {
private String name;
private String doNotSerialize;
#JsonCreator
public SimpleClass( #JsonProperty("name") String name ) {
this.name = name;
}
public String getName() {
return name;
}
public int getSum() {
return 1+1;
}
}
What I'm hoping is that somehow I can tell Jackson to treat all the constructor parameters as serializable fields, and all other fields / setters as non-serializable.
You can use a filter to only serialise getters which have a matching field, e.g.
package org.example;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import java.io.IOException;
import java.io.StringWriter;
public class App {
#JsonFilter("test")
public static class SimpleClass {
private String name;
private String doNotSerialize;
public SimpleClass(String name ) {
this.name = name;
}
public String getName() {
return name;
}
public int getSum() {
return 1+1;
}
}
public static void main( String[] args ) throws IOException {
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter("test", new SimpleBeanPropertyFilter() {
#Override
protected boolean include(BeanPropertyWriter writer) {
return super.include(writer);
}
#Override
protected boolean include(PropertyWriter writer) {
String name = writer.getName();
Class clazz = writer.getMember().getDeclaringClass();
try {
clazz.getDeclaredField(name);
return super.include(writer);
} catch (NoSuchFieldException e) {
// ignore
return false;
}
}
});
ObjectMapper mapper = new ObjectMapper();
mapper.setFilterProvider(filterProvider);
StringWriter sw = new StringWriter();
mapper.createGenerator(sw).writeObject(new SimpleClass("foo"));
System.out.println(sw.toString());
}
}
I don't know your full requirements, but this should be a start.
I haven't tried to do what you actually, asked, that is, look at constructor parameters, but that should be possible too.
If you want "sum" to be included in the serializad json but want to ignore it when deserializing you can do:
#JsonIgnoreProperties(ignoreUnknown=true)
public class SimpleClass {
// properties/getters
public int getSum() { return 1+1; }
}
If you want to remove "sum" entirely from the json you can do
#JsonIgnoreProperties({"sum"})
public class SimpleClass {
// properties/getters
public int getSum() { return 1+1; }
}
or
public class SimpleClass {
// properties/getters
#JsonIgnore
public int getSum() { return 1+1; }
}

Access to class attributes' values using Java Annotations

I am working with a java example using annotations, I created a simple POJO (java bean) using annotations to its attributes. I want to have the ability to create new objects of this type and retrieve the values of its attributes using the annotations created.
My POJO :
import java.io.Serializable;
import annotations.BusinessObject;
import annotations.BusinessObjectAttribute;
import annotations.BusinessObjectName;
import annotations.BusinessObjectPolicy;
import annotations.BusinessObjectRevision;
import annotations.BusinessObjectVault;
#BusinessObject
public class IndusTask implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
// Mandatory to create new object !
#BusinessObjectName
private String taskName;
#BusinessObjectRevision
private String taskRevision;
#BusinessObjectVault
private String vault;
// Mandatory to invoke iTask.create(context, policy) in Database
#BusinessObjectPolicy
private String policy;
//Specific attributes
#BusinessObjectAttribute
private String taskDescription;
#BusinessObjectAttribute
private String creationDate;
#BusinessObjectAttribute
private Integer weight;
public IndusTask() {
}
public IndusTask(String taskName, String taskRevision, String vault, String policy, String taskDescription,
String creationDate, Integer weight) {
super();
this.taskName = taskName;
this.taskRevision = taskRevision;
this.vault = vault;
this.policy = policy;
this.taskDescription = taskDescription;
this.creationDate = creationDate;
this.weight = weight;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public String getTaskRevision() {
return taskRevision;
}
public void setTaskRevision(String taskRevision) {
this.taskRevision = taskRevision;
}
public String getVault() {
return vault;
}
public void setVault(String vault) {
this.vault = vault;
}
public String getTaskDescription() {
return taskDescription;
}
public void setTaskDescription(String taskDescription) {
this.taskDescription = taskDescription;
}
public String getCreationDate() {
return this.creationDate;
}
public void setCreationDate(String creationDate) {
this.creationDate = creationDate;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public String getPolicy() {
return policy;
}
public void setPolicy(String policy) {
this.policy = policy;
}
}
Example of attributes' declaration:
*Business Object Type declaration
package annotations;
import java.lang.annotation.*;
//#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface BusinessObject {
}
*Business Object Name Attribute:
package annotations;
import java.lang.annotation.*;
//#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
public #interface BusinessObjectName {
}
I Created a main to test if all the annotations are detected:
public class MainImpl {
public static void main(String[] args) {
// TODO Auto-generated method stub
IndusTask myTask = new IndusTask("mytstTask", "001", "eService Production", "TstTask Process",
"myTstTask Description", "2018/02/16#15:30:10:GMT", 200);
System.out.println(myTask.getClass().getAnnotations().length);
}
}
Output is displaying 1 ! so only the first annotation is detected !
I was told also that the object attributes values can be accessed using these annotation (something similar to) :
object.getClass().getAnnotations()
How can i do ?
You need to iterate through the fields, get their annotations and set the value wherever the annotation matches (it can match multiple fields):
#Retention(RetentionPolicy.RUNTIME)
public #interface Field1 {}
#Retention(RetentionPolicy.RUNTIME)
public #interface Field2 {}
public static class UnderTest {
#Field1
private String field1;
#Field2
private int field2;
public UnderTest(String field1, int field2) {
this.field1 = field1;
this.field2 = field2;
}
#Override
public String toString() {
return field1 + "=" + field2;
}
}
public static void setter(Object obj, Class<? extends Annotation> fieldAnnotation, Object fieldValue) throws IllegalAccessException {
for (Field field: obj.getClass().getDeclaredFields()) {
for (Annotation annot: field.getDeclaredAnnotations()) {
if (annot.annotationType().isAssignableFrom(fieldAnnotation)) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(obj, fieldValue);
}
}
}
}
public static void main(String[] argv) throws IllegalAccessException {
UnderTest underTest = new UnderTest("A", 1);
System.out.println(underTest);
setter(underTest, Field1.class, "B");
setter(underTest, Field2.class, 2);
System.out.println(underTest);
}
Running this prints
A=1
B=2
Sounds like you're after the annotations on the fields too?
E.g. for the first private field:
myTask.getClass().getDeclaredFields()[0].getAnnotations()
Note depending how you're accessing a private field, you will sometimes also need to first ensure it is accessible:
...getDeclaredFields()[0].setAccessible(true);
[edit]
The values are reachable too from the fields. A basic worked example:
for (Field f : myTask.getClass().getDeclaredFields()) {
f.setAccessible(true);
System.out.println(f.getName() + "=" + f.get(myTask));
System.out.println(" annotations=" + java.util.Arrays.toString(f.getAnnotations()));
}

#JsonIgnore and #JsonProperty on same attribute

I need to ignore certain attributes in my Json Object based on a custom Ignore annotation, which I need only for a certain object mapper. But, for other cases, I need the JsonProperty annotation on it. I am using JacksonAnnotationInstrospector to do this. But when I do so, neither of the annotations get acknowledged.
For instance, I want my output to be such:
Normal object mapper:{"element3":"C","element_1":"A","element_2":"B"}
Expected output using Object mapper with JacksonAnnotationInstrospector:{"element_1":"A"}
The output I am actually getting with JacksonAnnotationInstrospector:{"element2":"B","element_1":"A"}
Following is my code:
public class TestClass {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setAnnotationIntrospector(new JsonIgnoreIntrospector());
MockObject mockObject = new MockObject("A", "B", "C");
String string = objectMapper.writeValueAsString(mockObject);
System.out.println(string);
}
public static class MockObject {
#JsonProperty("element_1")
String element1;
#CustomJsonIgnore
#JsonProperty("element_2")
String element2;
#CustomJsonIgnore
String element3;
public MockObject(String element1, String element2, String element3) {
this.element1 = element1;
this.element2 = element2;
this.element3 = element3;
}
public String getElement1() {
return element1;
}
public void setElement1(String element1) {
this.element1 = element1;
}
public String getElement2() {
return element2;
}
public void setElement2(String element2) {
this.element2 = element2;
}
public String getElement3() {
return element3;
}
public void setElement3(String element3) {
this.element3 = element3;
}
}
public static class JsonIgnoreIntrospector extends JacksonAnnotationIntrospector {
#Override
public boolean hasIgnoreMarker(final AnnotatedMember m) {
return m.hasAnnotation(CustomJsonIgnore.class) || m.hasAnnotation(JsonIgnore.class);
}
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.CONSTRUCTOR})
#JacksonAnnotation
public #interface CustomJsonIgnore {
}
}
You should use annotation on getters rather than on fields. and also add METHOD in annotation target.
working solution:
public class TestClass {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setAnnotationIntrospector(new JsonIgnoreIntrospector());
MockObject mockObject = new MockObject("A", "B", "C");
String string = objectMapper.writeValueAsString(mockObject);
System.out.println(string);
}
public static class MockObject {
String element1;
String element2;
String element3;
public MockObject(String element1, String element2, String element3) {
this.element1 = element1;
this.element2 = element2;
this.element3 = element3;
}
#JsonProperty("element_1")
public String getElement1() {
return element1;
}
public void setElement1(String element1) {
this.element1 = element1;
}
#CustomJsonIgnore
#JsonProperty("element_2")
public String getElement2() {
return element2;
}
public void setElement2(String element2) {
this.element2 = element2;
}
#CustomJsonIgnore
public String getElement3() {
return element3;
}
public void setElement3(String element3) {
this.element3 = element3;
}
}
public static class JsonIgnoreIntrospector extends JacksonAnnotationIntrospector {
#Override
public boolean hasIgnoreMarker(final AnnotatedMember m) {
return m.hasAnnotation(CustomJsonIgnore.class) || m.hasAnnotation(JsonIgnore.class);
}
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE,
ElementType.CONSTRUCTOR })
#JacksonAnnotation
public #interface CustomJsonIgnore {
}
}
I am not totally sure if I understand you use case. Why do you need a name on a property that you are ignoring?
If the issue is related to deserialisation and the deserialisation fails because it cannot find the desired property with a specific name, you can configure the object mapper to ignore unknown properties. Example follows.
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

How to Convert Java Object to XML object with java keyword

I create an java class:
public class ReturnObj {
private String returncode;
private String returndesc;
private Pkg pkg;
public String getReturncode() {
return returncode;
}
public void setReturncode(String returncode) {
this.returncode = returncode;
}
public String getReturndesc() {
return returndesc;
}
public void setReturndesc(String returndesc) {
this.returndesc = returndesc;
}
}
and other class:
public class Pkg {
private String packagecode;
private String cycle;
private String price;
private String desc;
public String getPackagecode() {
return packagecode;
}
public void setPackagecode(String packagecode) {
this.packagecode = packagecode;
}
public String getCycle() {
return cycle;
}
public void setCycle(String cycle) {
this.cycle = cycle;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
And I Want to convert object ReturnObj to this XML
<return>
<returncode>1</returncode>
<returndesc>DANG_KY_THANH_CONG</returndesc>
<package>
<packagecode>BD30</packagecode>
<cycle>1</cycle>
<price>15000</price>
<desc> BD30</desc>
</package>
</return>
So how do I serialize an attribute pkg to package in XML? Because Java doesn't allow to name variable as an keyword anh package is an keyword in Java !
You can use JAXB marshling in your class it will convert the object to XML, here is link to help you JAXB Marshling
Try xstream
XStream xstream = new XStream();
xstream.alias("package", Pkg.class);
String xml = xstream.toXML(myReturnObj);
You can use JAXB API that comes with java for converting java object to XML.
Below is the code that will solve your requirement.
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "return")
public class ReturnObj {
private String returncode;
private String returndesc;
private Pkg pkg;
public Pkg getPkg() {
return pkg;
}
#XmlElement(name = "package")
public void setPkg(Pkg pkg) {
this.pkg = pkg;
}
public String getReturncode() {
return returncode;
}
#XmlElement(name = "returncode")
public void setReturncode(String returncode) {
this.returncode = returncode;
}
public String getReturndesc() {
return returndesc;
}
#XmlElement(name = "returndesc")
public void setReturndesc(String returndesc) {
this.returndesc = returndesc;
}
}
#XmlRootElement
public class Pkg {
private String packagecode;
private String cycle;
private String price;
private String desc;
public String getPackagecode() {
return packagecode;
}
#XmlElement(name="packagecode")
public void setPackagecode(String packagecode) {
this.packagecode = packagecode;
}
public String getCycle() {
return cycle;
}
#XmlElement(name="cycle")
public void setCycle(String cycle) {
this.cycle = cycle;
}
public String getPrice() {
return price;
}
#XmlElement(name="price")
public void setPrice(String price) {
this.price = price;
}
public String getDesc() {
return desc;
}
#XmlElement
public void setDesc(String desc) {
this.desc = desc;
}
}
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class JAXBExample {
private static final String FILE_NAME = "C:\\ru\\jaxb-returnObj.xml";
public static void main(String[] args) {
ReturnObj returnObj = new ReturnObj();
returnObj.setReturncode("1");
returnObj.setReturndesc("DANG_KY_THANH_CONG");
Pkg pkg = new Pkg();
pkg.setCycle("1");
pkg.setPrice("15000");
pkg.setDesc("BD30");
returnObj.setPkg(pkg);
jaxbObjectToXML(returnObj);
}
private static void jaxbObjectToXML(ReturnObj emp) {
try {
JAXBContext context = JAXBContext.newInstance(ReturnObj.class);
Marshaller m = context.createMarshaller();
// for pretty-print XML in JAXB
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
// Write to System.out, this will print the xml on console
m.marshal(emp, System.out);
// Write to File
m.marshal(emp, new File(FILE_NAME));
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
Explanation:
#XmlRootElement: This is a must have annotation for the Object to be used in JAXB. It defines the root element for the XML content.
#XmlElement: This will create the element. If you want to give some other name to the xml element when converting java object to xml then you can pass name attribute to the #XmlElement Example:
#XmlElement(name = "package")
Execute above code to see the desired output.
Happy Coding.

com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException

This is the frist time I am trying XStream. But when I try to parse my xml file i am getting this exception :
com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field xmlread.Type.type
---- Debugging information ----
field : type
class : xmlread.Type
required-type : xmlread.Type
converter-type : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
path : /root/type
line number : 10
version : 1.4.8
-------------------------------
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.handleUnknownField(AbstractReflectionConverter.java:501)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:357)
at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:263)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72)
at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50)
at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134)
at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1206)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1190)
at com.thoughtworks.xstream.XStream.fromXML(XStream.java:1061)
at xmlread.Main.main(Main.java:23)
So we can see that the error is on row 10 in my Type class.
And row 10 is the this line : #XStreamAlias("root")
package xmlread;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
#XStreamAlias("root")
public class Type {
#XStreamAlias("INFO")
private Info info;
#XStreamAlias("OBJECT_TYPE")
private String objectType;
#XStreamAlias("PROP")
private Properties prop;
#XStreamAlias("PARAM")
private List<Parameters> param;
#XStreamImplicit(itemFieldName = "type")
private List typeList = new ArrayList();
// metodo construtor
public Type() {
// TODO Auto-generated constructor stub
}
//Constructor, Getters and setters
public Info getInfo() {
return info;
}
public void setInfo(Info info) {
this.info = info;
}
public String getObjectType() {
return objectType;
}
public void setObjectType(String objectType) {
this.objectType = objectType;
}
public Properties getProp() {
return prop;
}
public void setProp(Properties prop) {
this.prop = prop;
}
public List<Parameters> getParam() {
return param;
}
public void setParam(List<Parameters> param) {
this.param = param;
}
public List getTypeList() {
return typeList;
}
public void setTypeList(List typeList) {
this.typeList = typeList;
}
}
And the xml looks like this :
<root>
<info>
<CORE_NAME>DataModel_Core</CORE_NAME>
<CORE_VERSION>..</CORE_VERSION>
<CORE_PRODUCT_ID>...</CORE_PRODUCT_ID>
<ADAPTATION_NAME />
<ADAPTATION_VERSION />
<ADAPTATION_PRODUCT_ID />
</info>
<type>
<OBJECT_TYPE>data</OBJECT_TYPE>
<prop>
<DESCRIPTION>Site parameters</DESCRIPTION>
<PARENT>NULL</PARENT>
<VIRTUAL>0</VIRTUAL>
<VISIBLE>1</VISIBLE>
<PICTURE>NULL</PICTURE>
<HELP>10008</HELP>
<MIN_NO>1</MIN_NO>
<MAX_NO>1</MAX_NO>
<NAME_FORMAT>NULL</NAME_FORMAT>
</prop>
<param>
<PARAMETER>nidRbc</PARAMETER>
<DATA_TYPE>INTEGER</DATA_TYPE>
<DESCRIPTION>RBC identity</DESCRIPTION>
<MIN_NO>1</MIN_NO>
<MAX_NO>1</MAX_NO>
<ORDER1>1</ORDER1>
<NESTED>0</NESTED>
<DEFAULT1>NULL</DEFAULT1>
<FORMAT>0:16382</FORMAT>
</param>
</type>
</root>
And my other classes looks like this :
package xmlread;
import java.io.*;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.XStreamException;
public class Main {
public static void main(String[] args) throws Exception {
try {
FileReader reader = new FileReader("enderecos.xml");
//String representacao = xstream.toXML(aluno);
XStream xstream = new XStream();
xstream.processAnnotations(Properties.class);
xstream.processAnnotations(Parameters.class);
xstream.processAnnotations(ObjType.class);
xstream.processAnnotations(Type.class);
Type data = (Type)xstream.fromXML(reader);
//Person newJoe = (Person)xstream.fromXML(xml);
System.out.println(data);
} catch (IOException io) {
io.printStackTrace();
} catch (XStreamException e) {
e.printStackTrace();
}
}
}
____________________________________________________________
package xmlread;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
#XStreamAlias("PARAM")
public class Parameters {
#XStreamAlias("DATATYPE")
private String datatype;
#XStreamAlias("DESCRIPTION")
private String description;
#XStreamAlias("MIN_NO")
private String min_no;
#XStreamAlias("MAX_NO")
private String max_no;
#XStreamAlias("ORDER1")
private String order1;
#XStreamAlias("NESTED")
private String nested;
#XStreamAlias("DEFAULT1")
private String default1;
#XStreamAlias("FORMAT")
private String format;
#XStreamAlias("PARAMETER")
private List<Parameters> parameter;
public Parameters(String datatype, String description, String min_no,
String max_no, String order1, String nested, String default1,
String format, List<Parameters> parameter) {
super();
setDatatype(datatype);
setDescription(description);
setMin_no(min_no);
setMax_no(max_no);
setOrder1(order1);
setNested(nested);
setDefault1(default1);
setFormat(format);
setParameter(parameter);
} // Getters and setters..
public Parameters() {
// TODO Auto-generated constructor stub
}
public String getDatatype() {
return datatype;
}
public void setDatatype(String datatype) {
this.datatype = datatype;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getMin_no() {
return min_no;
}
public void setMin_no(String min_no) {
this.min_no = min_no;
}
public String getMax_no() {
return max_no;
}
public void setMax_no(String max_no) {
this.max_no = max_no;
}
public String getOrder1() {
return order1;
}
public void setOrder1(String order1) {
this.order1 = order1;
}
public String getNested() {
return nested;
}
public void setNested(String nested) {
this.nested = nested;
}
public String getDefault1() {
return default1;
}
public void setDefault1(String default1) {
this.default1 = default1;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public List<Parameters> getParameter() {
return parameter;
}
public void setParameter(List<Parameters> parameter) {
this.parameter = parameter;
}
}
____________________________________________________________
package xmlread;
import com.thoughtworks.xstream.annotations.XStreamAlias;
#XStreamAlias("prop")
public class Properties {
#XStreamAlias("DESCRIPTION")
private String description;
#XStreamAlias("PARENT")
private String parent;
#XStreamAlias("VIRTUAL")
private String virtual;
#XStreamAlias("VISIBLE")
private String visible;
#XStreamAlias("PICTURE")
private String picture;
#XStreamAlias("HELP")
private String help;
#XStreamAlias("MIN_NO")
private String min_no;
#XStreamAlias("MAX_NO")
private String max_no;
#XStreamAlias("NAME_FORMAT")
private String name_format;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getParent() {
return parent;
}
public void setParent(String parent) {
this.parent = parent;
}
public String getVirtual() {
return virtual;
}
public void setVirtual(String virtual) {
this.virtual = virtual;
}
public String getVisible() {
return visible;
}
public void setVisible(String visible) {
this.visible = visible;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public String getHelp() {
return help;
}
public void setHelp(String help) {
this.help = help;
}
public String getMin_no() {
return min_no;
}
public void setMin_no(String min_no) {
this.min_no = min_no;
}
public String getMax_no() {
return max_no;
}
public void setMax_no(String max_no) {
this.max_no = max_no;
}
public String getName_format() {
return name_format;
}
public void setName_format(String name_format) {
this.name_format = name_format;
}
public static void setInstance(Properties instance) {
Properties.instance = instance;
}
public static Properties instance = null;
public static Properties getInstance() {
if (instance == null) {
instance = new Properties();
}
return instance;
}
public Properties() {
// TODO Auto-generated constructor stub
}
}
____________________________________________________________
package xmlread;
import com.thoughtworks.xstream.annotations.XStreamAlias;
#XStreamAlias("INFO")
public class Info {
#XStreamAlias("CORE_NAME")
private String core_name;
#XStreamAlias("CORE_VERSION")
private String core_version;
#XStreamAlias("CORE_PRODUCT_ID")
private String core_product_id;
#XStreamAlias("ADAPTATION_NAME")
private String adaptation_name;
#XStreamAlias("ADAPTATION_VERSION")
private String adaptation_version;
#XStreamAlias("ADAPTATION_PRODUCT_ID")
private String adaptation_product_id;
public Info(String core_name, String core_version, String core_product_id,
String adaptation_name, String adaptation_version,
String adaptation_product_id) {
super();
setCore_name(core_name);
setCore_version(core_version);
setCore_product_id(core_product_id);
setAdaptation_name(adaptation_name);
setAdaptation_version(adaptation_version);
setAdaptation_product_id(adaptation_product_id);
}
public String getCore_name() {
return core_name;
}
public void setCore_name(String core_name) {
this.core_name = core_name;
}
public String getCore_version() {
return core_version;
}
public void setCore_version(String core_version) {
this.core_version = core_version;
}
public String getCore_product_id() {
return core_product_id;
}
public void setCore_product_id(String core_product_id) {
this.core_product_id = core_product_id;
}
public String getAdaptation_name() {
return adaptation_name;
}
public void setAdaptation_name(String adaptation_name) {
this.adaptation_name = adaptation_name;
}
public String getAdaptation_version() {
return adaptation_version;
}
public void setAdaptation_version(String adaptation_version) {
this.adaptation_version = adaptation_version;
}
public String getAdaptation_product_id() {
return adaptation_product_id;
}
public void setAdaptation_product_id(String adaptation_product_id) {
this.adaptation_product_id = adaptation_product_id;
}
}
____________________________________________________________
package xmlread;
import com.thoughtworks.xstream.annotations.XStreamAlias;
#XStreamAlias("OBJECT_TYPE")
public class ObjType {
#XStreamAlias("OBJECT_TYPE")
private String objectType;
public ObjType() {
} // Getters and setters
public String getObjectType() {
return objectType;
}
public void setObjectType(String objectType) {
this.objectType = objectType;
}
}
Whats the cause of this error?
package xmlread;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
#XStreamAlias("root")
public class SomeOtherClass {
#XStreamAlias("INFO")
private Info info;
#XStreamAlias("TYPE")
private Type type;
#XStreamImplicit(itemFieldName = "type")
private List typeList = new ArrayList();
// metodo construtor
public SomeOtherClass() {
// TODO Auto-generated constructor stub
}
//Constructor, Getters and setters
public void setType(Type type){
this.type = type;
}
public Type getType() {
return this.type;
}
public Info getInfo() {
return info;
}
public void setInfo(Info info) {
this.info = info;
}
}
class Type {
#XStreamAlias("OBJECT_TYPE")
private String objectType;
#XStreamAlias("PROP")
private Properties prop;
#XStreamAlias("PARAM")
private List<Parameters> param;
public String getObjectType() {
return objectType;
}
public void setObjectType(String objectType) {
this.objectType = objectType;
}
public Properties getProp() {
return prop;
}
public void setProp(Properties prop) {
this.prop = prop;
}
public List<Parameters> getParam() {
return param;
}
public void setParam(List<Parameters> param) {
this.param = param;
}
}

Categories