I am trying to unmarshall a list of error objects.
requestContext.abortWith(Response.status(Response.Status.FORBIDDEN).entity(
new GenericEntity<List<Error>>(errors){})
.type(MediaType.APPLICATION_JSON_TYPE).build());
The unmarshalled JSON looks like
{"error":[{"code":5,"detail":"app level of request, 2, does not meet the minimum required app level, 5"}]}
However I want my json array to be named errors instead of error. This is the java class definition of Error
#XmlRootElement
public class Error {
#XmlElement
private Integer code;
#XmlElement
private String detail;
public Error(Integer code, String detail) {
this.code = code;
this.detail = detail;
}
public Error() {}
}
How can I achieve this?
By default, it uses #XmlRootElement. So you will need to use #JsonRootName
#JsonRootName("errors")
#XmlRootElement
public class Error {
Related
I am new to Spring Boot and I am trying to figure out how to parse json data. I see a lot of tutorials on how to map json string object to an annotated Java class and using and object mapper, like this:
json:
{
"UUID": "xyz",
"name": "some name"
}
public class MyClass{
#JsonProperty
private UUID id;
#JsonProperty
private String name;
#JsonAnyGetter
public UUID getId() {
return this.id;
}
#JsonAnySetter
public void setId(UUID id) {
this.id = id;
}
#JsonAnyGetter
public String getName() {
return this.name;
}
#JsonAnySetter
public void setName(String name) {
this.name = name;
}
}
ObjectMapper objectMapper = new ObjectMapper();
MyClass customer = objectMapper.readValue(jsonString, MyClass.class);
The problem is that the system I am getting the json string from does not match the class naming conventions we use (and I cannot change either one). So, instead of having the example json string above, it might look like this:
{
"randomdstring-fieldId": "xyz",
"anotherrandomstring-name": "some name"
}
This use case only has two fields, but my use case has a larger payload. Is there a way to either map the field names from the json object to the field names in the Java class or is there a way to just parse the json string as a key value pair (so that I can just manually add the fields to my Java object)?
In Jackson with #JsonProperty you can customize the field name with it's annotation parameter value
Therefore, you just have to annotate the entity fields with the #JsonProperty annotation and provide a custom JSON property name, like this:
public class MyClass{
#JsonProperty("original_field_name_in_json")
private UUID id;
...
The #JsonProperty will do it for you:
#JsonProperty("name_in_json")
private Long 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?
I am using Spring #RequestBody to map a JSON payload to a Java Object. Unfortunately this JSON payload does not use a set convention but rather has names that use both camelCase and snake_case.
To be clear my Controller looks like this:
#RequestMapping(value="/mobile/device", method = RequestMethod.PUT)
public ResponseEntity<Object> flagDevice (#RequestBody List<MobileDeviceData> deviceInfoList) {
... code here ...
}
with the MobileDeviceData Entity object having several setter methods like:
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public void setFlagId(int flagId) {
this.flagId = flagId;
}
This works great and without any extra effort when the JSON objects name is camelCase. However for snake_case names I need to add the Annotation:
#JsonProperty("flag_id")
private int flagId;
in order for it to be picked up.
I know it's not a good idea to use the #JsonProperty if it can be avoided as you then will need to annotate every parameter. My question is, is there a more general way to enforce matching snake_case with the corresponding camelCase in the Entity object? And obviously to do it without screwing up the ones that are already camelCase.
As per the article here, there is a simple approach to deserialize the MobileDeviceData class. Here is the sample code as below:
#JsonDeserialize(using = UserDeserializer.class)
public class User {
private ObjectId id;
private String username;
private String password;
public User(ObjectId id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
public ObjectId getId() { return id; }
public String getUsername() { return username; }
public String getPassword() { return password; }
}
Assume User is the class we’re interested in writing the Deserializer for. Not much is notable here, except for the annotations that tell Jackson who knows how deserialize this class.
public class UserDeserializer extends JsonDeserializer {
#Override
public User deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException {
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
return new User(null,
node.get("username").getTextValue(),
node.get("password").getTextValue());
}
}
The deserializer is created by extending Jackson’s abstract JsonDeserializer class, and giving it the type we want to deserialize to. Difficult is figuring out that you can reference the JSON by field name with the JsonParser's ObjectCodec.
I hope it helps.
Please feel free to comment if needed!
Having been working on this a bit, I now realize doing anything like what was requested would be counterproductive.
When you receive (deserialize) a JSON Object, it is generally expected that you will deliver (serialize) with the same parameters. If an implementation extracted both camelCase and underscore parameters the same way, then it would not know how to deserialize correctly later on. By following a standard convention and then using #JsonProperty for all the exceptions, it remains possible to deserialize and later deliver the JSON object just as it was received.
I've a POJO and I want to create an instance of this class from JSON. I'm using jackson for converting JSON to Object. I want to ensure that JSON will conain all properties of my POJO. The JSON may contain other extra fields but it must contain all the attributes of the POJO.
Example:
class MyClass {
private String name;
private int age;
public String getName(){return this.name;}
public void setName(String name){this.name = name;}
public int getAge(){return this.age;}
public void setAge(int age){this.age = age;}
}
JSON #1
{
"name":"Nayan",
"age": 27,
"country":"Bangladesh"
}
JSON #2
{
"name":"Nayan",
"country":"Bangladesh"
}
Here, I want JSON#1 to be successfully converted to MyClass but JSON#2 should fail. How can I do this? Is there an annotation for this?
Well, there is an annotation that you could apply to your properties that say they are required.
#JsonProperty(required = true)
public String getName(){ return this.name; }
The bad part is, as of right now (2.5.0), validation on deserialization isn't supported.
...
Note that as of 2.0, this property is NOT used by BeanDeserializer: support is expected to be added for a later minor version.
There is an open issue from 2013 to add validation: Add support for basic "is-required" checks on deserialization using #JsonProperty(required=true)
I'm trying to use jcouchdb (https://code.google.com/p/jcouchdb/) for accessing my CouchDB instance from Java. I have some JSon documents that I'd like to parse into Java classes - with Svenson, used in jcouchdb, and then put those parsed objects into DB. I generate this JSON objects with AVRO (http://avro.apache.org) JSon Encoder, they seem to be ok, but apparently other parsers have problems with them.
My JSon strings look like this:
{
"id":40,
"event_id":"48764322212",
"note":{
"string":"ABC note"
},
"created_date":null,
"event_category":null,
"city":null,
"address":null
}
Which seems valid JSON - validated with http://jsonformatter.curiousconcept.com/
However my Svenson object defined like this:
public class Note {
Long id;
String eventId;
String note;
String createdDate;
String eventCategory;
String city;
String address;
#JSONProperty()
public Long getId() {
#JSONProperty("event_id")
public String getEventId() {
#JSONProperty("note")
public String getNote() {
#JSONProperty("created_date")
public String getCreatedDate() {
#JSONProperty("event_category")
public String getEventCategory() {
#JSONProperty("city")
public String getCity() {
#JSONProperty("address")
public String getAddress() {
}
(setters and getters' bodies intentionally removed)
The error when parsing is:
Cannot set property string on class java.lang.String
It seems that this JSON is parsed correctly (there is a difference in note field):
{
"id":40,
"event_case_id":"000-123123123",
"event_msisdn":"48764322212",
"note":"Planowana data portacji: 2011/01/27 11:42:49",
"created_date":null,
"event_category":null,
"city":null,
"address":null
}
How can I work this out? Perhaps there is another json library that would work for me?
You declare note as a java.lang.String:
public String getNote()
but in the JSON you declare it as an Object with a property named "string":
"note":{
"string":"ABC note"
}
You need to change the JSON or the Bean to match each other. For example, in the second functioning JSON, you declared the JSON note as a string. This is why it works.