I have the following piece of code
#XStreamAlias("Pa")
public class Pa {
#XStreamAsAttribute
private String ms;
#XStreamAsAttribute
private String co;
#XStreamAsAttribute
private String house;
#XStreamAsAttribute
private String street;
// Getters and Setters
}
I want my attributes names to be different from the variable names when my XML is constructed.
I know I can do it to classes with the following annotation
#XStreamAlias("ExampleClass")
private ExClass exClass;
The above code will result in a tag with the name
<ExampleClass/>
However, I cannot find any annotation that changes the name of the attribute without creating a separate tag.
What I want is the following:
<Pa milliseconds="" co =""/>
But using
#XStreamAlias("Milliseconds")
private String ms;
is creating a new tag with the given name. It no longer stays an attribute of the tag.
Does such an annotation exist? I need to do it only using annotations, not at runtime using Java code.
Thank you for your time.
You should use both annotations:
#XStreamAlias("Pa")
public class Pa {
#XStreamAsAttribute
#XStreamAlias("Milliseconds")
String ms = "test";
public static void main(String[] args) {
XStream xStream = new XStream();
xStream.ignoreUnknownElements();
xStream.processAnnotations(Pa.class);
String xml = xStream.toXML(new Pa());
System.out.println(xml);
}
}
output:
<Pa Milliseconds="test"/>
Related
I am quite new to Java and I am trying to deserialize the JSON using Jackson and I facing some minor issue with regards to declaring the Object/Variable type. I will provide all the codes then explain the issue for easy understanding.
I have an enum that will have the required type values:
public enum IdentifierTypeValues {
Type1,
Type2,
Type3,
//Constructor and Getter of enum values
}
Then for each of these type, I have different classes which will have different input and do a completely different type of process:
public class GenerateType1 {
private String name;
private String age;
//Getter and Setter
//Some required process based on these values
}
public class GenerateType2 {
private String address;
private String city;
private String country;
//Getter and Setter
//Some required process based on these values
}
public class GenerateType3 {
private String firstName;
private String lastName;
private String fullName;
//Getter and Setter
//Some required process based on these values
}
Now I have a wrapper class for these type of classes which will take the type based on enum and typeInfo values. I want the typeInfo values to be any of the class based type something like this:
public class TypeSyntax {
private IdentifierTypeValues indeitiferType;
private GenerateType1 / GenerateType2 / GenerateType3 identifierTypeValues;
//Here the identifierTypeValues can have the values for anytype
//How to declare a variable of any of these class type?
}
This is the class that will be used by my JSON for deserializing. I know I can add a wrapper class of those 3 types and provide that wrapper class as a type class for this. Something like this:
public class WrapperClass{
private GenerateType1 type1;
private GenerateType2 type2;
private GenerateType3 type3;
}
public class TypeSyntax{
private IdentifierTypeValues indeitiferType;
private WrapperClass identifierTypeValues;
//But using this approach will change my JSON structure which I do not want to do.
}
My JSON structure is something like this and I would like to keep it in the same way.
{
"indeitiferType":"Type1",
"identifierTypeValues":{
"name":"Batman",
"age":"2008"
}
}
Is there a way I can declare the variable of multiple type class? or any better approach to handle this by keeping the json format same? I tried searching but I am unable to search what exactly so any help would be really appriciated.
Because the type identifier exists on a different level than the other properties a wrapper class TypeSyntax needed. There are several open feature requests to add wrapping functionality to Jackson e.g. https://github.com/FasterXML/jackson-databind/issues/512
Fortunately polymorphism is supported in Jackson with #JsonTypeInfo and #JsonSubTypes annotations.
Wrapper class should look like:
public class TypeSyntax {
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "identifierType")
private GenerateTypeBase identifierTypeValues;
// getters and setters (omitted for brevity)
}
GenerateTypeBase is the common parent class
#JsonSubTypes({
#JsonSubTypes.Type(value = GenerateType1.class, name = "Type1"),
#JsonSubTypes.Type(value = GenerateType2.class, name = "Type2"),
})
public abstract class GenerateTypeBase {
private String name;
private String age;
// getters and setters (omitted for brevity)
}
In this different children classes will instantiated based on the identifierType property.
The children must extend this base class:
public class GenerateType2 extends GenerateTypeBase {
// additional properties
}
In a short test it will be:
#Test
void wrapperTest() throws IOException {
ObjectMapper mapper = new ObjectMapper();
GenerateType2 a = new GenerateType2();
a.setName("Foo");
a.setAge("13");
TypeSyntax w = new TypeSyntax();
w.setIdentifierTypeValues(a);
String json = mapper.writeValueAsString(w);
System.out.println(json);
}
and the output:
{
"identifierTypeValues":
{
"name":"Foo",
"age":"13"
},
"identifierType":"Type2"
}
Deserialization
#Test
void wrapperTest() throws IOException {
ObjectMapper mapper = new ObjectMapper();
String input = "{\"identifierTypeValues\": \"name\":\"Foo\",\"age\":\"13\"},\"identifierType\":\"Type2\"}";
TypeSyntax w = mapper.readValue(new StringReader(input), TypeSyntax.class);
assertAll(
() -> assertEquals(GenerateType2.class, o.getIdentifierTypeValues().getClass()),
() -> assertEquals("13", o.getIdentifierTypeValues().getAge())
);
}
If you want more flexibility you can write custom (de)serializer and / or custom resolver. Using custom TypeIdResolver that will possible to convert identifiers to types programmatically instead of using "key-value pairs" in #JsonSubTypes
Is there any way to serialize a class into json but only with fields I want to use in particular case without need of creating multiple variations of class?
Let's take an example:
class User{
#JsonField
private String name;
#JsonField
private String surname;
#JsonField
private String hashedCode;
#JsonField
private String city;
#JsonField
private String anotherDummyString;
}
Now in one of my methods I would like to have a mapping to json Object which only contains name, city and anotherDummyString.
In Second method I want to have surname and city. In third method ... .
Is there any pleasant and neat way to achive this?
I was wondering if I can "hide" these fields which I don't need.
Are you looking for something like this? (Using javax.json)
JsonObject getJson1() {
return Json.createObjectBuilder().add("name", this.name).add("city", this.city).build();
}
JsonObject getJson2() {
return Json.createObjectBuilder().add("surname", this.surname).add("city", this.city).build();
}
Just .add what you need in each function call.
I hope you are looking for a kind of filter for your fields in Class
This can be achieved using Jackson #JsonFilter
package com.concretepage;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonProperty;
#JsonFilter("student")
public class Student
{
#JsonProperty("name")
private String name;
#JsonProperty("surname")
private String surname;
#JsonProperty("hashedCode")
private String hashedCode;
#JsonProperty("city")
private String city;
#JsonProperty("anotherDummyString")
private String anotherDummyString;
}
Create a simple filter for you above class
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter("student",
SimpleBeanPropertyFilter.serializeAllExcept("name", "city","anotherDummyString"));
Set it to a object mapper
ObjectMapper mapper = new ObjectMapper();
mapper.setFilterProvider(filterProvider);
To get the json message
//Pass the student object
String jsonData = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(student);
You must able to have you 2 variance of class by creating one more sample filter like above
I need to unmarshall a xml file which can return tag in following two ways.
<return_msg>Invalid Bank Code.</return_msg>
Second one
<return_msg>
<status_desc>Ok</status_desc>
<status_code>0</status_code>
</return_msg>
How can I create JAXB model class for this tag
Haven't tried, but you should be able to use this :
#XmlRootElement(name="return_msg")
#XmlAccessorType(XmlAccessType.FIELD)
public class ReturnMsg{
#XmlElement
private String status_desc;
#XmlElement
private String status_code;
#XmlMixed
private List<String> mixedContent;
//Getters and Setters
}
The mixed content should contains your "Invalid Bank Code." message if it's there.
I want to unmarshall an XML and the elements of a node are present in multiple class files, I need to to know if we can create #XmlElement tag 2 times with the same name and pass the same node to two different classes
I have the following XML:
<data>
<properties>
<id>ID123</id>
<name>sss</name>
<note>note</note>
</properties>
</data>
root class file
#XmlRootElement(name="data")
public class Data {
prop1 prop1;
prop2 prop2;
#XmlElement(name="properties")
public prop1 getProp1(){
return this.prop1;
}
public void setProp1(prop1 prop1){
this.prop1 = prop1;
}
#XmlElement(name="properties")
public prop2 getProp2(){
return this.prop2;
}
public void setProp2(prop2 prop2){
this.prop2 = prop2;
}
}
public class prop1{
private String id;
private String name;
#XmlElement(name="id")
//setters and getters for id node
#XmlElement(name="name")
//setters and getters for name node
}
public class prop2{
private String note;
#XmlElement(name="note")
//setters and getters for note node
}
I have id, name in prop1 class and note in prop2 class. And all the elements are under one node.
Can I delcare Data class with #XmlElement tag two times with the same name and pass the same node to two different classes? I tried this but able to create an instance of only prop1 class.
Looking for other options too to handle this scenario
Firstly, do you really need to do it. Why cannot you have properties class from which you will get wrappers from Note part and Id/Name part.
One way, is to map the xml properites as it is in xml and used the marshaling/unmarshaling events to convert it to the your prop classes.
public class Properties {
#XMLElement
String id;
#XMLElement
String name;
#XMLElement
String note;
}
public class Data {
#XMLElement
Properties properties;
#XMLTransient
Prop1 prop1
....
void afterUnmarshal(Unmarshaller unm, Object parent) {
prop1.id = properties.id;
prop1.name = prperites.name;
prop2.note = properties.note;
};
boolean beforeMarshal(Marshaller mar) {
prop1 = new Prop1(properties.id,properties.name);
prop2 = new Prop2(properties.note);
};
}
So you need additional container (Properties) to store the value, but it will work with any jaxb implementation.
To avoid the container you could you XMLAdapter and jaxb extension that uses XMLTransforamtion to extract necessary parts from your xml node.
You can find the description with an example partially your case here:
http://blog.bdoughan.com/2010/08/xmltransformation-going-beyond.html
But is based on eclipse implementation of jaxb and it requires a substantial amount of code.
I got a requirement that I have to map my xml to java object without parsing it, but the problem is like that in xml tag names would be same, for example,
<response>
<employee>
<name>Sharique</name>
<name>24</name>
<name>India</name>
</employee>
</response>
and class would be like this
public class Employee{
private String empName;
private int age;
private String country;
//getters and setters
}
Please help!!
If it can be done using spring than that would be very nice
If you leverage EclipseLink MOXy as your JAXB (JSR-222) provider then you can use our #XmlPath extension for this use case.
#XmlAccessorType(XmlAccessType.FIELD)
public class Employee{
#XmlPath("name[1]/text()")
private String
#XmlPath("name[2]/text()")
private int age;
#XmlPath("name[3]/text()")
private String country;
//getters and setters
}
For More Information
I have written more about the #XmlPath extension on my blog:
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
Not required, As per javax.xml.bind.annotation you can do like below,
#XmlElement(name="name")
private String empName;
So now the empName in your java class will be mapped to name attribute in your XML.
and your XML should not have 'name' as name for all attributes. it cannot differentiate, so you need to use different tags in your XML for other elements like age and so on ans map accordingly as i stated above in your POJO.
You really got some weird XML there. I thing data binding will not help in this case, but you can do it with data projection. (Disclosure: I'm affilited with that project)
public class ParseResponse {
public interface Employee {
#XBRead("./name[1]")
String getName();
#XBRead("./name[2]")
int getAge();
#XBRead("./name[3]")
String getCountry();
}
public static void main(String[] args) {
List<Employee> employees = new XBProjector().io().url("res://response.xml").evalXPath("//employee").asListOf(Employee.class);
for (Employee employee:employees) {
System.out.println(employee.getName());
System.out.println(employee.getAge());
System.out.println(employee.getCountry());
}
}
}
this program prints out
Sharique
24
India
if you fix the XML closing tags.