I have a json object like this
{
"id":23 ,
"key": "AKEY",
"description": {
"plain": {
"value": "This is an example",
"representation": "plain"
}
}
}
I'd like to map it to this object
public class JsonResponse {
private int id;
private String key;
private String name;
private String type;
private String description;
/*usual getters and setters*/
}
I use the JSONSerialiser like this
JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(responseEntity);
But how do I map the "description.plain.value" to "JsonResponse.description"?
Can this be done using jackson annotations?
thanks for your help
I found this post Binding JSON child object property into Java object field in Jackson that partially solved my problem.
I wrote two setDescription() methods, one used by myself in my code, and one that's been called by jacskon
#JsonProperty(value = "description")
public void setDescription(Map<String, Map<String,String>> description) {
this.description = description.get("plain").get("value");
}
public void setDescription(String description) {
this.description = description;
}
It looks like the JsonProperty annotation is required to make jackson use the right setter.
Still I'm ok with this as long as it is a "short nested" property, but I guess Beri response is more acceptable with complex JSON responses.
Related
In my Spring project I have several objects that should be serialized to a specific JSON format.
public class Person {
private Integer id;
private String name;
private String height;
private Address address;
}
and
public class Address {
private String street;
private String city;
private String phone;
}
Let assume that Person.height and Address.phone should not appear in the JSON.
The resulting JSON should look like
{
"attributes": ["id", "name", "street", "city"],
"values": [12345, "Mr. Smith", "Main street", "Chicago"]
}
I can create create a standard JSON with an ObjectMapper and some annotations like #JsonProperty and #JsonUnwrapped where I disable some SerializationFeatures. But at the moment I'm not able to create such a JSON.
Is there an easy way to create this JSON? And how would the way back (deserialization) look like?
There are good reasons Jackson doesn't serializes maps in this format. It's less readable and also harder to deserialize properly.
But if you just create another POJO it's very easy to achieve what you want to do:
public class AttributeList {
public static AttributeList from(Object o) {
return from(new ObjectMapper().convertValue(o, new TypeReference<Map<String, Object>>() {}));
}
public static AttributeList from(Map<String, Object> attributes) {
return new AttributeList(attributes);
}
private final List<String> attributes;
private final List<Object> values;
private AttributeList(Map<String, Object> o) {
attributes = new ArrayList<>(o.keySet());
values = new ArrayList<>(o.values());
}
}
At the deserialization process (which as I understand is the process of converting JSON data into a Java Object), how can I tell Jackson that when it reads a object that contains no data, it should be ignored?
I'm using Jackson 2.6.6 and Spring 4.2.6
The JSON data received by my controller is as follows:
{
"id": 2,
"description": "A description",
"containedObject": {}
}
The problem is that the object "containedObject" is interpreted as is and it's being instantiated. Therefore, as soon as my controller reads this JSON data, it produces an instance of the ContainedObject object type but I need this to be null instead.
The easiest and fastest solution would be that in the JSON data received, this value be null like this:
{
"id": 2,
"description": "A description",
"containedObject": null
}
But this isn't possible since I'm not in control of the JSON data that is sent to me.
Is there an annotation (like this explained here) that works for the deserialization process and could be helpfull in my situation?
I leave a representation of my classes for more information:
My entity class is as follows:
public class Entity {
private long id;
private String description;
private ContainedObject containedObject;
//Contructor, getters and setters omitted
}
And my contained object class as follows:
public class ContainedObject {
private long contObjId;
private String aString;
//Contructor, getters and setters omitted
}
I would use a JsonDeserializer. Inspect the field in question, determine, if it is emtpy and return null, so your ContainedObject would be null.
Something like this (semi-pseudo):
public class MyDes extends JsonDeserializer<ContainedObject> {
#Override
public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
//read the JsonNode and determine if it is empty JSON object
//and if so return null
if (node is empty....) {
return null;
}
return node;
}
}
then in your model:
public class Entity {
private long id;
private String description;
#JsonDeserialize(using = MyDes.class)
private ContainedObject containedObject;
//Contructor, getters and setters omitted
}
Hope this helps!
You can implement a custom deserializer as follows:
public class Entity {
private long id;
private String description;
#JsonDeserialize(using = EmptyToNullObject.class)
private ContainedObject containedObject;
//Contructor, getters and setters omitted
}
public class EmptyToNullObject extends JsonDeserializer<ContainedObject> {
public ContainedObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
long contObjId = (Long) ((LongNode) node.get("contObjId")).numberValue();
String aString = node.get("aString").asText();
if(aString.equals("") && contObjId == 0L) {
return null;
} else {
return new ContainedObject(contObjId, aString);
}
}
}
Approach 1 : This is mostly used. #JsonInclude is used to exclude properties with empty/null/default values.Use #JsonInclude(JsonInclude.Include.NON_NULL) or #JsonInclude(JsonInclude.Include.NON_EMPTY) as per your requirement.
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Employee {
private String empId;
private String firstName;
#JsonInclude(JsonInclude.Include.NON_NULL)
private String lastName;
private String address;
private String emailId;
}
More info about the jackson annotations : https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations
Approach 2 : GSON
use GSON (https://code.google.com/p/google-gson/)
Wondering if anyone can help me figure out away to assign the body context to my description String variable.
Here is my JSON string
{"requirement":{"description":{"body":"This is a text"}}}
public class Requirement implements Serializable {
private String description;
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
}
I know I can use #JsonProperty("description") but my description is nested with different context. In this case I only care about the body.
If you don't want to have the class with same structure as the json, you'll have to first unpack the description object and extract body:
public class Requirement {
private String body;
#JsonProperty("description")
private void unpackNested(Map<String,Object> description) {
this.body = (String)description.get("body");
}
}
Your data structure actually looks like this
class Requirement{
private Description description;
}
class Description{
private String body;
}
just add proper #JsonProperty and you will be fine.
In general, every json Object is a separate class (unless you map to plan maps)
My question is kind of similar to Prevent GSON from serializing JSON string but the solution there uses GSON library and I am restricted to using Jackson (fasterxml).
I have an entity class as follows:
package com.dawson.model;
import com.dawson.model.audit.BaseLongEntity;
import lombok.extern.log4j.Log4j;
import javax.persistence.*;
#Table(name = "queue", schema = "dawson")
#Entity
#Log4j
public class Queue extends BaseLongEntity {
protected String requestType;
protected String body;
protected Queue() {
}
public Queue(String requestType, String body) {
this.requestType = requestType;
this.body = body;
}
#Column(name = "request_type")
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
#Column(name = "body")
#Lob
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
I want to populate the body field with the json string representation of a map and then send this as part of the ResponseEntity. Something as follows:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.writer().withDefaultPrettyPrinter();
HashMap<String, String> map = new HashMap<>(5);
map.put("inquiry", "How Can I solve the problem with Jackson double serialization of strings?");
map.put("phone", "+12345677890");
Queue queue = null;
try {
queue = new Queue("General Inquiry", mapper.writeValueAsString(map));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
String test = mapper.writeValueAsString(map)
System.out.println(test);
Expected Output: "{"requestType": "General Inquiry","body": "{"inquiry":"How Can I solve the problem with Jackson double serialization of strings?","phone":"+12345677890"}"}"
Actual Output:"{"requestType": "General Inquiry","body": "{\"inquiry\":\"How Can I solve the problem with Jackson double serialization of strings?\",\"phone\":\"+12345677890\"}"}"
I am using
Jackson Core v2.8.2
I tried playing with
#JsonIgnore
and
#JsonProperty
tags but that doesn't help because my field is already serialized from the map when writing to the Entity.
Add the #JsonRawValue annotation to the body property. This makes Jackson treat the contents of the property as a literal JSON value, that should not be processed.
Be aware that Jackson doesn't do any validation of the field's contents, which makes it dangerously easy to produce invalid JSON.
I have a question regarding a web-application I'm building where I have a REST service receiving a json string.
The Json string is something like:
{
"string" : "value",
"string" : "value",
"object" : {
"string" : "value",
"string" : "value",
....
}
}
I'm using resteasy to parse the json string which uses jackson underneath. I have a jaxb annotated class and I want to parse the "object" entirely into a String variable. The reason I want to do this is to be able to parse the json later using the correct parser (it depends on the application that sends the request so it is impossible to know in advance).
My jaxb annotated class looks like this:
#XmlRootElement
#XmlAccessorType(XmlAccessType.PROPERTY)
public class Test{
#XmlElement(type = String.class)
private String object;
//getter and setter
...
}
When I execute the rest call and let jackson parse this code I get an
Can not deserialize instance of java.lang.String out of START_OBJECT token
error. So actually I'm trying to parse a piece of a json string, which is a json object, into a String. I can't seem to find someone with a similar problem.
Thanks in advance for any response.
java.lang.String out of START_OBJECT token
this means that expected character after "object" is quotes ", but not brackets {.
Expected json
"object" : "my object"
Actual json
"object" : { ...
=======
If you want parse json like in your example, then change your class. E.g.
#XmlRootElement
#XmlAccessorType(XmlAccessType.PROPERTY)
public class Test{
#XmlElement
private InnerTest object;
//getter and setter
...
}
#XmlAccessorType(XmlAccessType.PROPERTY)
public class InnerTest{
#XmlElement
private String string;
//getter and setter
...
}
If I understand this question you just want a mechnanism, that converts a Java-Object into a JSON-String and the other way.
I needed this as well, while I was using a WebSocket Client-Server communication where a JSON String has been passed around.
For this I used GSON (see GSON). There you got the possibility to create a complete JSON-String.
Here some example:
// Converts a object into a JSON-String
public String convertMyClassObjectToJsonFormat() {
MyClass myObject = new MyClass();
Gson gson = new Gson();
return gson.toJson(myObject);
}
//Converts a JSON-String into a Java-Class-Object
public MyClass convertJsonToMyClassObject(
CharBuffer jsonMessage) {
Gson gson = new Gson();
return gson.fromJson(jsonMessage.toString(),
MyClass.class);
}
What you need is, that you your Class-Attributes-setter and JSON-Attribute-names are equivalent. E.g.
{
"info":[
{
"name": "Adam",
"address": "Park Street"
}
]
}
Your Class should look like this:
public class Info{
private String name;
private String address;
public void setName(String name){
this.name = name;
}
public void setAddress(String address){
this.address = address;
}
}
#KwintenP Try using the json smart library.
You can then simply retrieve the JSON object first using:
JSONObject test = (JSONObject) JSONValue.parse(yourJSONObject);
String TestString = test.toString();
What's more, you can retrieve a specific object inside a JSON object may it be another object, an array and convert it to a String or manipulate the way you want.
you also can do something like this ;
public class LeaderboardView
{
#NotEmpty
#JsonProperty
private String appId;
#NotEmpty
#JsonProperty
private String userId;
#JsonProperty
private String name = "";
#JsonProperty
private String imagePath = "";
#NotEmpty
#JsonIgnore
private String rank = "";
#NotEmpty
#JsonProperty
private String score;
public LeaderboardView()
{
// Jackson deserialization
}
}