Can we change instance variable name with special character in jaxb - java

I am using JAXB and jersey for my project. Here is my model class:
#XmlRootElement(name="volume")
#JsonRootName(value="volume")
public class Volume{
#XmlAttribute(name="os-vol:name")
public String name;
}
Desire Output:
{"volume":{"os-vol:name":"vol-1"}}
Is there any way so that i could change the instance variable "name" to "os-vol:name" in both xml and json. I used #JsonProperty,but it worked for JSON only. Any other way so that it can represent both JSON as well as XML simultaneously.

Use the annotation JsonProperty:
#JsonProperty(name="os-vol:name")
public String name;

Related

Jackson naming convention issue in serialization with uncommon getter method name

New to java and spring boot.
While trying to serialize the following class,
public class ActionItems {
private String APpID;
public String getAPpID() {
return APpID;
}
public void setAPpID(String aPpID) {
APpID = aPpID;
}
// other fields
}
got the json string as
{
"appID": null,
}
Whilst, cross checking the getter name with decapitilize(), it is matching with the field name.
Introspector.decapitalize("APpID") - gives "APpID"
Is jackson using a different set of rules and methods when generating the property name from the getter method?
PS: I am aware that, variable name should begin with small case. While going through the java beans naming convention spec got this question.
I am using jackson 2.9.3v.
PS: As per the link PropertyNamingStrategy, it should have produced APpID instead of appId right?
Could someone provide some input here?
Thanks.
In Jackson, you can custom PropertyNamingStrategy, and
In absence of a registered custom strategy, default Java property
naming strategy is used, which leaves field names as is, and removes
set/get/is prefix from methods (as well as lower-cases initial
sequence of capitalized characters).
Also, you can custom a property name like:
#JsonProperty("APpID") // produce {"APpID":"s"}
public String getAPpID() {
return APpID;
}

How does gson maps JSON keys with the fields in Java classes while deserializing the JSON

I am searching for this for quite some time now but still, it is not clear to me. I have a JSON file which looks like this:
{
"Name" : "Foo Bar",
"Grade" : "Some Grade",
"Org" : "Some Org"
}
For deserializing this JSON (using gson) I have created a Java class called StudentDetails.java which looks like this:
public class StudentDetails
{
public String name;
public String grade;
public String org;
}
Now I have a couple of questions regarding this:
Will gson automatically maps the fields in StudentDetails.java with corresponding keys even if the fields start with lower case and keys start from upper case in the JSON file. I have looked for #SerializedName but my code works without even using it. On the contrary if I am using something like #SerializedName("Name) with name field, it's getting assigned to null after deserialization. I am so confused right now.
Will deserialization work without even getter and setter methods? In jackson you write setter and getter methods.
If above is true, does it work even in the case of private fields?
I'm note sure about this one but i think the case only matters after the first character because you normally don't start the name of field with an upper-case character.
Yes GSON will automatically map the fields.
Yes GSON does not need getter/setter
(https://stackoverflow.com/a/6203975/4622620)
Yes GSON can handle private fields because it uses reflections (https://stackoverflow.com/a/28927525/4622620)

Use JAXB Annotation With Value

When generating XML using JAXB annotations, I know it's not possible to use #XmlElement(name="City") & #XmlValue on the same Java member because they are mutually exclusive. Is it possible to #XmlElement to produce an XML tag with a value at the same time? Not being able to do this causes a ton of objects to be created and seems to be overkill.
Java Code
....
#XmlElement(name="City")
#XmlValue <---- I'm wanting to do this but I'm limited by the API
private String city;
Expected Output
....
<City>some value here</City>
....
We can try to achieve the same using another type which uses #XmlValue annotation.
Below is what you can try -
#XmlRootElement(name="CityRoot")
#XmlType(name="CityRootType")
public class CityRoot {
#XmlElement(name="City")
public CityName s;
}
CityName definition as below
public class CityName {
#XmlValue
String name;
}
Now, feed these two files to schemagen to have the .xsd file generated and using that generate .xml file to verify.
Below is how generated xml file looks like when I generated it -
<?xml version="1.0" encoding="UTF-8"?>
<CityRoot>
<City>SomeCityName</City>
</CityRoot>
If you want to have an element with simple text, the only annotation you need is the #XmlElement annotation. If the type of a field is String, JAXB generates an xml element with the value of the String as the value of the element.
The only thing you need is this:
#XmlElement(name="City")
private String city;

How to JSON parse immutable object in Java + Jersey

So I am just trying out Jersey for REST services and it seems to we working out fine. I only expose get services and all of the object types that I expose with these services have an immutable object representation in Java. By default Jersey seems to use a parser (JAXB?), requiring a #XmlRootElement annotation for the class that should be parsed, zero-arg constructor and setters.
I have been using Gson with no zero-arg constructor, no setters and final on all fields with no problems at all. Is there any way to accomplish this with Jersey(i.e. the paser it is using)? I have seen solutions with adapter classes that map data from a immutable object to a mutable representation, but this seems like a lot of boilerplate(new classes, more annotations, etc.) if it can be achieved with Gson without anything added.
Note: 1) I have heard people promote using zero-arg constructor and claim that Gson should not work without it. This is not what I am interested in. 2) I really have tried googling this but my keywords might be off. In other words, humiliate me in moderation.
EDIT 1:
My webservice works if I do like this:
#XmlRootElement
public class Code{
private String code; //Silly object just used for example.
public Code(){}
//(G || S)etters
}
With this class exposing the object:
#GET
#Produces(MediaType.APPLICATION_JSON)
public Set<Code> get(#QueryParam("name") String name) { // Here I want to use a class of my own instead of String name, haven't figured out how yet.
return this.codeService.get(name);
}
If I replace the Code with the following, the webservice stops working:
public class Code{
private final String code;
#JsonCreator
public Code(#JsonProperty("code") String code) {
this.code = code;
}
//Getters omitted
}
What I want is to be able to 1) have immutable objects that can be parsed to/from json and 2) Be able to define something like #RequestBody in Spring MVC for my incoming objects.
Actually this could be pretty easy with Genson. You just need the jar and then configure the Genson feature to use constructors with arguments (if you don't want to put annotations on it).
Genson genson = new GensonBuilder().useConstructorWithArguments(true).create();
// and then register it with jersey
new ResourceConfig().register(new GensonJaxRSFeature().use(genson));
Or you can use JsonProperty on the arguments. See the User Guide for more details.

Marshal an object as one of its properties with Jackson (as for value objects i.e primitive types wrappers)

EDIT: Previous answer does not work (it stills create a nested object)
I'm using Jersey and Jackson.
I got a class like
#XmlAccessorType(XmlAccessType.NONE)
public class Name {
private String value;
#XmlValue
public String getValue(){...}
public void setValue(String value){...}
}
used as in
public class Person{
#XmlElement(name = "IDName")
public Name getName(){...}
}
I'd like to marshal Name object as the value of it's identity property.
How can I achieve that?
<Person>
<IDName>foo</IDName>
</Person>
instead of
<Person>
<IDName>
<Value>foo</Value>
</IDName>
</Person>
I'd tried both to indicate in Person that Name object should be marshalled as itself.getValue() and either to indicate within Name class to marshal without any element wrapper (its fields directly) with no luck.
A possible solution is replacing #XmlValue annotation with Jackson's #JsonValue to make it work (tested).
I infer from http://wiki.fasterxml.com/JacksonJAXBAnnotations that it can be the only solution for now
According to this the official documentation
#javax.xml.bind.annotation.XmlValue
The field/property to which this annotation is applied will be named "value".
So maybe it's limited by design. Any better answer, specially if using JAXB annotations alone, will be much appreciated

Categories