I have an API built in Java Spring that return (using JacksonJaxbJsonProvider 2.5.5) a JSON object from this class:
public class FieldValues {
private String code;
private Object value;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
In the main object I've
#JsonRootName(value = "WorkRequest")
#XmlRootElement(name = "WorkRequest")
#JsonIgnoreProperties(ignoreUnknown = true)
public class WorkRequestDTOResponse {
private List<FieldValues> fieldValues;
public List<FieldValues> getFieldValues() {
return fieldValues;
}
public void setFieldValues(List<FieldValues> fieldValues) {
this.fieldValues = fieldValues;
}
}
But the output of the fieldValues object is this:
"fieldValues": [
{
"code": "anomaly",
"value": {
"#xsi.type": "ns3:boolean",
"$": "true"
}
},{
"code": "internal_note",
"value": {
"#xsi.type": "ns3:string",
"$": "Test text example"
}
}
]
instead what I need is this:
"fieldValues": [
{
"code": "anomaly",
"value": true
},{
"code": "internal_note",
"value": "Test text example"
}
]
This is my JSON Provider:
public class ErmesJSONProvider extends JacksonJaxbJsonProvider {
public ErmesJSONProvider() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
mapper.configure(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, false);
_mapperConfig.setMapper(mapper);
_mapperConfig.getConfiguredMapper().setAnnotationIntrospector(new JacksonAnnotationIntrospector());
}
}
Trying to use a String instead an object:
public class FieldValues {
private String code;
private String value;
But if I set this value as String fieldValues.setValue("true"), the JSON output is "value": true instead "value": "true"
Likewise if I set this value as String but with an Integer fieldValues.setValue("1"), the JSON output is "value": 1 instead "value": "1"
If I print the return object using ObjectMapper I've the right JSON:
String payload = new ObjectMapper().writeValueAsString(requestResult)
but if I return a Response like this:
return Response.status(Response.Status.CREATED).entity(new GenericEntity<RequestResult>(requestResult){}).build()
it return the wrong JSON.
I can't understand why 😥
Someone can help me? Thanks.
Related
I got the following JSON that im trying to deserialize:
{
"items": [
{
"id": 29000012,
"name": "Crystal League I",
"iconUrls": {
"small": "https://api-assets.clashofclans.com/leagues/72/kSfTyNNVSvogX3dMvpFUTt72VW74w6vEsEFuuOV4osQ.png",
"tiny": "https://api-assets.clashofclans.com/leagues/36/kSfTyNNVSvogX3dMvpFUTt72VW74w6vEsEFuuOV4osQ.png",
"medium": "https://api-assets.clashofclans.com/leagues/288/kSfTyNNVSvogX3dMvpFUTt72VW74w6vEsEFuuOV4osQ.png"
}
},
{
"id": 29000015,
"name": "Master League I",
"iconUrls": {
"small": "https://api-assets.clashofclans.com/leagues/72/olUfFb1wscIH8hqECAdWbdB6jPm9R8zzEyHIzyBgRXc.png",
"tiny": "https://api-assets.clashofclans.com/leagues/36/olUfFb1wscIH8hqECAdWbdB6jPm9R8zzEyHIzyBgRXc.png",
"medium": "https://api-assets.clashofclans.com/leagues/288/olUfFb1wscIH8hqECAdWbdB6jPm9R8zzEyHIzyBgRXc.png"
}
}
],
"paging": {
"cursors": {}
}}
Im trying to deserialize it with the following DTO:
#JsonRootName("items")
#JsonIgnoreProperties(value={ "paging" })
public class League {
private Long id;
private String name;
private IconUrls iconUrls;
public League() {
}
}
class IconUrls {
private String small;
private String tiny;
private String medium;
public IconUrls() {
}
}
But im getting the following error:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Root name ('items') does not match expected ('List') for type `java.util.List<gg.stats.wrapper.entities.League>
I have also set: DeserializationFeature.UNWRAP_ROOT_VALUE
This is the call of the method from my Client:
List<League> getLeagueList();
The problem might be the "paging" key.
Any workaround for that?
I actually found a solution by myself:
#JsonIgnoreProperties(value={ "paging" }, allowGetters=true)
public class ResponseWrapper<T> {
private List<T> items;
#JsonProperty("items")
public List<T> getResponseContent() {
return this.items;
}
#JsonProperty("items")
public void setResponseContent(List<T> items) {
this.items = items;
}
}
I am reading one file through which I need to create a specific JSON structure to pass it on UI, but I am unable to write a code for JSON formation. So I created one Java class initialized my class, tried a lot but still now able to find a way, how to form it. Here is my main Java class where I am adding an element like this
public class DynamicListForming {
public static void main(String[] args) {
NodeInfo cab = new NodeInfo("saurabh", "South");
NodeInfo cab1 = new NodeInfo("South", "ZONE1");
NodeInfo cab2 = new NodeInfo("ZONE1", "Street-1");
NodeInfo cab3 = new NodeInfo("ZONE1", "Street-2");
NodeInfo cab4 = new NodeInfo("ZONE1", "Street-3");
NodeInfo cab5 = new NodeInfo("ZONE1", "Street-4");
List<NodeInfo> NodeInfos = new LinkedList<NodeInfo>();
NodeInfos.add(cab);
NodeInfos.add(cab1);
NodeInfos.add(cab2);
NodeInfos.add(cab3);
NodeInfos.add(cab4);
NodeInfos.add(cab5);
}
}
My NodeInfo class looks like this
public class NodeInfo {
private String nodeName;
private String parentName;
private List<NodeInfo> children;
public NodeInfo(String parentName, String nodeName) {
super();
this.parentName = parentName;
this.nodeName = nodeName;
}
public String getNodeName() {
return nodeName;
}
public void setNodeName(String nodeName) {
this.nodeName = nodeName;
}
public String getParentName() {
return parentName;
}
public void setParentName(String parentName) {
this.parentName = parentName;
}
public List<NodeInfo> getChildren() {
return children;
}
public void setChildren(List<NodeInfo> children) {
this.children = children;
}
}
I need to form JSON structure like below
"nodeInfo": {
"name": "saurabh",
"children": [
{
"name": "SOUTH",
"children": [
{
"name": "Zone-1",
"children": [
{
"name": "Street-1"
},
{
"name": "Street-2"
},
{
"name": "Street-3"
},
{
"name": "Street-4"
}
]
}
]
}
]
}
Any suggestion on how to form this type of JSON structure, I struggled a lot and unable to find a way to dynamically create a list and object to form this structure.
I'm trying to use gson to deserialize some data that I'm getting back from a SonarQube API on various code metrics. This is an example of the raw JSON coming back from the server:
{
"component": {
"id": "c5fc9d6k-e28b-4ea0-8922-df18c7e07ac1",
"key": "APP:master",
"name": "master",
"qualifier": "TRK",
"measures": [
{
"metric": "coverage",
"value": "19.9",
"periods": [
{
"index": 1,
"value": "0.09999999999999787"
},
{
"index": 2,
"value": "0.09999999999999787"
},
{
"index": 3,
"value": "0.6999999999999993"
},
{
"index": 4,
"value": "8.7"
}
]
},
{
"metric": "overall_coverage",
"value": "55.7",
"periods": [
{
"index": 1,
"value": "0.0"
},
{
"index": 2,
"value": "0.0"
},
{
"index": 3,
"value": "3.0"
},
{
"index": 4,
"value": "55.7"
}
]
},
{
"metric": "ncloc",
"value": "1089127",
"periods": [
{
"index": 1,
"value": "3835"
},
{
"index": 2,
"value": "3835"
},
{
"index": 3,
"value": "-74350"
},
{
"index": 4,
"value": "102501"
}
]
}
]
}
}
I'm attempting to deserialize it into a Component class with this code:
public Component getComponentMeasures(String componentKey, List<String> measures) throws ClientProtocolException,
IOException, JsonSyntaxException, UnsupportedOperationException, JSONException
{
HttpGet request = new HttpGet(baseURL + String.format("/api/measures/component?componentKey=%s&metricKeys=%s",
componentKey, StringUtils.join(measures, ",")));
HttpResponse response = client.execute(request);
Gson gson = new Gson();
String componenta = getJSONResponse(response);
System.out.print(componenta);
Component component = gson.fromJson(componenta, Component.class);
return component;
}
This is the Component class that I'm deserializing it into:
public class Component {
#SerializedName("id")
#Expose
private String id;
#SerializedName("key")
#Expose
private String key;
#SerializedName("name")
#Expose
private String name;
#SerializedName("qualifier")
#Expose
private String qualifier;
#SerializedName("path")
#Expose
private String path;
#SerializedName("measures")
#Expose
private Measure[] measures = null;
public String getId() {
return id;
}
public String getKey() {
return key;
}
public String getName() {
return name;
}
public String getQualifier() {
return qualifier;
}
public String getPath() {
return path;
}
public Measure[] getMeasures() {
return measures;
}
}
This Component class also contains an array of Measures which in turn contain an array of periods.
Measure Class:
public class Measure {
#SerializedName("metric")
#Expose
private String metric;
#SerializedName("value")
#Expose
private String value;
#SerializedName("periods")
#Expose
private Period[] periods = null;
public String getMetric() {
return metric;
}
public String getValue() {
return value;
}
public Period[] getPeriods() {
return periods;
}
}
Period class:
public class Period {
#SerializedName("index")
#Expose
private Integer index;
#SerializedName("value")
#Expose
private String value;
public Integer getIndex() {
return index;
}
public String getValue() {
return value;
}
}
When I run this code, the deserialized component is null. Any ideas on anything that I may be doing wrong here? Note that there is an extra parameter in the Component class, "path", that is null in the JSON. This is optional and exists in other classes which contain a collection of Component objects. In those cases, this Component object and JSON deserialize fine. I've compared the JSON side-by-side and they are identical. I only seem to have the issue when trying to deserialize a standalone component object. Any help would be greatly appreciated!
Note that your JSON document is a JSON object with a single property (the path: $.component) with a nested component, however you're trying to deserialize it as if it were the top-most object:
Component component = gson.fromJson(componenta, Component.class);
Just create another class to match the top-most single property object, say something like:
final class Response {
#SerializedName("component")
#Expose
final Component component = null;
}
And then sample code like
final Response response = gson.fromJson(componenta, Response.class);
for ( final Measure measure : response.component.measures ) {
System.out.println(measure.metric + " " + measure.value);
}
will print the following output:
coverage 19.9
overall_coverage 55.7
ncloc 1089127
Sonar has an SDK for their API that encapsulates all of this and you don't have to create your own classes, etc. I used it to get info out like you're doing. See https://docs.sonarqube.org/display/SONARQUBE45/Using+the+Web+Service+Java+client and my use of it: http://myvogonpoetry.com/wp/2013/02/21/using-the-sonar-rest-api-for-weekly-emails/
I am sending json from ajax to controller that contain multiple array.
Json Data:
{
"node": [
{
"id": "dev_1",
"blockId": "11"
},
{
"id": "dev_2",
"blockId": "15"
}
],
"connect": [
{
"id": "con_5",
"typeId": "2"
}
],
"name": "test"
}
Controller:
#RequestMapping(value = "/saveBoard", method = RequestMethod.POST)
public JsonResponse saveBoard(#RequestBody String jsonData) throws IOException {
JsonResponse response = new JsonResponse();
ObjectMapper mapper = new ObjectMapper();
final JsonNode jsonNode = mapper.readTree(jsonData).get("node");
if(jsonNode.isArray()) {
for (final JsonNode nodes : jsonNode) {
System.out.println("jsonNode : "+ nodes);
}
}
return response;
}
I have tried with object mapper but not succeed.
Here i want to read different array for different classes like node for node class with some specified fields, connect for connect class and string for another use.
UPDATE
Contorller:
#RequestMapping(value = "/saveBoard", method = RequestMethod.POST)
public JsonResponse saveMissionBoard(#RequestBody MissionJsonPojo chartJson) {
boolean status = false;
String messsage = "";
JsonResponse response = new JsonResponse();
System.out.println("data : " + flowChartJson.getNodes());
return response;
}
Ajax:
$.ajax({
url: '<c:url value="/board/saveBoard"/>',
type: 'POST',
data: JSON.stringify(chartJson),
dataType: "json",
contentType: "application/json",
success: function(response) {
console.log("In success");
},
error: function (a, b, c) { }
});
JSON:
{
"nodes": [
{
"missionDeviceId": "device_1",
"device": "1",
"deviceXCoordinate": 79,
"deviceYCoordinate": 73,
"blockId": "1##1"
},
{
"missionDeviceId": "device_2",
"device": "3",
"deviceXCoordinate": 340,
"deviceYCoordinate": 146,
"blockId": "2##5"
}
],
"connections": [
{
"missionConnectionId": "con_5",
"sourceId": "device_1",
"targetId": "device_2",
"device": "2"
}
],
"name": "test"
}
Node Pojo:
public class Nodes{
private String missionDeviceId;
private Integer device;
private String deviceXCoordinate;
private String deviceYCoordinate;
private String blockId; //getters setters
}
Connection Pojo:
public class Connections{
private String missionConnectionId;
private String sourceId;
private String targetId;
private Integer device; //getters and setters
}
MissionJsonPojo:
public class MissionJsonPojo{
private List<Nodes> nodes;
private List<Connections> connections;
private String name; //getters and setters
}
As suggested by #dambros, create a POJO structure like this:
public class Node {
private String id;
private String blockId;
//setter-getters.
}
public class Connect {
private String id;
private String typeId;
//setter-getters.
}
import java.util.List;
public class Payload {
private List<Node> nodes;
private List<Connect> connects;
private String name;
//setter-getters
}
And change your method signature to:
public JsonResponse saveBoard(#RequestBody Payload payload) throws IOException {
}
This should solve your problem.
I am using Gson to get convert the object to json string, and its working fine but when I am sending that json to a webservice method using post, I have to add the post method's parameter name in the string.
Example:
jsonString I get from Gson new Gson().toJson(requestDataDTO) :
{
"req": {
"AppId": "2",
"ThirdParty": "3",
"UserId": "1",
"UserToken": "4"
},
"req1": {
"AppId": "-33",
"ThirdParty": "3",
"UserId": "1",
"UserToken": "4"
}
}
jsonString I want :
{
"requestDataDTO": {
"req": {
"AppId": "2",
"ThirdParty": "3",
"UserId": "1",
"UserToken": "4"
},
"req1": {
"AppId": "-33",
"ThirdParty": "3",
"UserId": "1",
"UserToken": "4"
}
}
}
for now I am adding this "requestDataDTO" string at the start of json string I got from Gson.
is there a way to achieve this ?
Assuming you have an object which looks somehow like this:
package com.dominikangerer.q25077756;
import com.google.gson.annotations.SerializedName;
public class RequestDataDTO {
// {"AppId":"2","ThirdParty":"3","UserId":"1","UserToken":"4"}
#SerializedName("AppId")
private String appId;
#SerializedName("ThirdParty")
private String thirdParty;
#SerializedName("UserId")
private String userId;
#SerializedName("UserToken")
private String userToken;
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getThirdParty() {
return thirdParty;
}
public void setThirdParty(String thirdParty) {
this.thirdParty = thirdParty;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserToken() {
return userToken;
}
public void setUserToken(String userToken) {
this.userToken = userToken;
}
}
The easiest and also for me most readable solution would be to create an wrapper/container Class which contains a HashMap (key/value) like this:
package com.dominikangerer.q25077756;
import java.util.HashMap;
public class RequestDataDTOContainer {
private HashMap<String, RequestDataDTO> requestDataDTO = new HashMap<String, RequestDataDTO>();
public HashMap<String, RequestDataDTO> getRequestDataDTO() {
return requestDataDTO;
}
public void setRequestDataDTO(HashMap<String, RequestDataDTO> requestDataDTO) {
this.requestDataDTO = requestDataDTO;
}
public void putRequestDataDTO(String key, RequestDataDTO value){
this.requestDataDTO.put(key, value);
}
}
To run it simply test it with a main like this:
// enable pretty printing
Gson gson = new GsonBuilder().setPrettyPrinting().create();
// too lazy to fill the objects by hand
String reqJson = "{\"AppId\":\"2\",\"ThirdParty\":\"3\",\"UserId\":\"1\",\"UserToken\":\"4\"}";
String req1Json = "{\"AppId\":\"-33\",\"ThirdParty\":\"3\",\"UserId\":\"1\",\"UserToken\":\"4\"}";
// deserialize it with gson
RequestDataDTO req = gson.fromJson(reqJson, RequestDataDTO.class);
RequestDataDTO req1 = gson.fromJson(req1Json, RequestDataDTO.class);
// initiliaze the container
RequestDataDTOContainer container = new RequestDataDTOContainer();
// adding the 2 req objects with the certain key
container.putRequestDataDTO("req", req);
container.putRequestDataDTO("req1", req1);
// Print it as pretty json
System.out.println(gson.toJson(container));
You are now more flexibility if you want to add more meta information like a whole meta object or similar without adding a hardcoded String to that json.
You can find the whole Example in this github repository: Java Stackoverflow Answers by DominikAngerer