I've been trying many solutions from similar solved problems in this page but I can't make it work. I'm making a get petition to obtain an array JSON, and I want to map those values into my class.
I got this class:
public class Devices {
private String DeviceName;
private String DeviceDescription;
public String getDeviceName() {
return DeviceName;
}
public void setDeviceName(String deviceName) {
this.DeviceName = deviceName;
}
public String getDeviceDescription() {
return DeviceDescription;
}
public void setDeviceDescription(String deviceDescription) {
this.DeviceDescription = deviceDescription;
}
}
The GET petition returns this JSON below:
[{"DeviceName":"AMIXT-20EC-VIDM0000","DeviceDescription":"Samsung device "},{"DeviceName":"AMIXT-E0F9-VIDM0001","DeviceDescription":"Tablet Huawei"}]
I've tried solutions like this one (also tried with getForObject):
ResponseEntity<Devices[]> responseEntity = restTemplate.getForEntity(url, Devices[].class);
As we can see in this photo, the body properties are null
What am I missing?
The issue is related to the name of the fields in the JSON, name start with an upper-case letter.
One simple solution would be to use #JsonProperty annotation on the variables defined in the Devices class
public class Devices {
#JsonProperty("DeviceName")
private String deviceName;
#JsonProperty("DeviceDescription")
private String deviceDescription;
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getDeviceDescription() {
return deviceDescription;
}
public void setDeviceDescription(String deviceDescription) {
this.deviceDescription = deviceDescription;
}
}
Related
I have two controllers in my micro service both are POST and accepts Request body as JSON, one is working fine and another one's JSON input from some othet team and it is with root class name , so I need to write custom object mapper for this later controller, could you please guys help,
please find the codes below,
#RestController
#Slf4j
public class Controller2 {
#RequestMapping(value = "/some/update", method = RequestMethod.POST)
public String updateEmd(#RequestBody final UpdateEMDRequest updateEMDRequest) throws JsonProcessingException {
updateEMDRequest.getBookingReference()); // null now
return "success";
}
}
and the sample json is as follows,
{
"UpdateEMDRequest":{
"TransactionStatus":"SUCCESS",
"UniqueTransactionReference":"046060420",
"PreAuthReference":"040520420",
"BookingReference":"8PJ",
"CarrierCode":"AS",
"TransactionMode":"Batch",
"CallBackUrl":"www.test.com/op/update",
"Offers":[
{
"Offer":{
"traveler":{
"firstName":"AHONY",
"surname":"DNEN",
"EMD":[
"081820470"
]
}
}
}
]
}
}
UpdateEMDRequest,java
#JsonInclude(Include.NON_NULL)
public class UpdateEMDRequest {
#JsonProperty("UniqueTransactionReference")
private String uniqueTransactionReference;
#JsonProperty("TransactionStatus")
private String transactionStatus;
#JsonProperty("PreAuthReference")
private String preAuthReference;
#JsonProperty("BookingReference")
private String bookingReference;
#JsonProperty("CarrierCode")
private String carrierCode;
#JsonProperty("TransactionMode")
private String transactionMode;
#JsonProperty("CallBackUrl")
private String callBackUrl;
#JsonProperty("Offers")
private List<Offers> offers;
}
So this json is not parsed properly and updateEMDRequest's properties are null always.
Here is an example:
class Person {
String name;
Address addressGiven;
//getters and setters
class Address {
#JsonProperty(name="stno")
private String StreetNo
#JsonProperty(name="type")
private AddressType addType;
public void setstno(String stno){
if (this.addressGiven==null)
addressGiven=new Address();
addressGiven.setStno(stno);
}
public void setType(String type) {
if (addressGiven==null){
addressGiven=new Address();
}
addressGiven.setType(AddressType.valueOf(type));
}
// other getters and setters
}
}
AddressType.java
Enum AddressType {
HOME,
OFFICE,
BUSINESS,
DEFAULT;
}
Two points to note before I go to my question:
Address in an inner class
the instance attribute addType is of enum type
when I serialize the object:
Person person = new Person();
Person.setStNo("1234");
person.setType("HOME");
ObjectMapper mapper = new ObjectMapper();
String body = mapper.writeValueAsString(person);
System.out.println(body);
I expect:
{
"addressGiven:
{ "stno" : "1234",
"type" : HOME,
}
}
but what I get is this :
{ "streetNo" : "1234"}.
Three noticable differences
nested json is missing
streetNo but not stno is returned
No addressType is present.
why is the expected json (i.e inner not returned. am I missing some annotations anywhere?
I browsed through jackson docs. but could not figure out sooner. so here I am?
Jackson will automatically call the empty constructor on the object is serializing. the exception being if a constructor is annotated with #JsonCreator, or a builder class annotated with #JsonPOJOBuilder, and maybe another one im missing. i would remove the creation of Address and also the checking for null. dummy down those setters/getters.
ObjecMapper by default handles serialization of an Enum. i would suggest removing that manual conversion
#see DeserializationFeature.READ_ENUMS_USING_TO_STRING. default value is false which means that it uses Enum.valueOf to serialize the String into the correct value.
with all that being said, you are expecting something that doesnt match your code. Person does not have an attribute type, nor stNo. those are Address attributes. im curious to know how you get the output shown. see below for code and example output
class Person {
private String name;
private Address addressGiven;
public void setName(String name) { this.name = name; }
public void setAddressGiven(Address addressGiven) { this.addressGiven = addressGiven; }
public String getName() { return name; }
public Address getAddressGiven() { return addressGiven; }
enum AddressType { HOME, OFFICE, BUSINESS, DEFAULT }
static class Address {
#JsonProperty("stno") private String streetNo;
#JsonProperty("type") private AddressType addType;
public String getStreetNo() { return streetNo; }
public void setStreetNo(String streetNo) { this.streetNo = streetNo; }
public AddressType getAddType() { return addType; }
public void setAddType(AddressType addType) { this.addType = addType;}
}
public static void main(String[] args) throws JsonProcessingException {
Person person = new Person();
person.name = "joe";
Address address = new Address();
address.addType = AddressType.BUSINESS;
address.streetNo = "010101";
person.addressGiven = address;
ObjectMapper mapper = new ObjectMapper();
String body = mapper.writeValueAsString(person);
System.out.println(body);
}
}
{"name":"joe","addressGiven":{"stno":"010101","type":"BUSINESS"}}
So my entities look like this:
public class HappyClass<T>
{
private String id;
prviate int ver;
private Object obj;
public String getId()
{
return this.id;
}
public void setId( String id )
{
this.id = id;
}
public int getVer()
{
return this.ver;
}
public void setVer( int ver )
{
this.ver = ver;
}
#JsonTypeInfo( use = Id.NONE )
public T getObj()
{
return obj;
}
public void setObj( T obj )
{
this.obj = obj;
}
}
public class HappyGeneric
{
private String someStuff();
public String getSomeStuff()
{
return this.someStuff();
}
public void setSomeStuff( String someStuff )
{
this.someStuff = someStuff;
}
}
If I instantiate a class like this:
HappyClass<HappyGeneric> hc = new HappyClass<HappyGeneric>();
If I send it to Spring in a #ResponseBody it returns this:
{
"id" : "iamsomeid",
"ver" : 123,
"obj" : {
"someStuff" : "iamsomestuff"
}
}
However, when Spring and/or Jackson attempts to unmarshal the same JSON, it figures out that the main class is a HappyClass, however, the getObj() it unmarshals to a LinkedHashMap and not a HappyGeneric no matter what I seem to annotate it with.
Anybody have any ideas how I can force Jackson to unmarshal that generic to the original class?
Thanks!
EDIT: I'm aware I can call mapper.convertValue( blah.getObj(), HappyGeneric.class ) and get the object out that way-- I was hoping to get Spring to figure it out automatically (through annotations, for example).
I am using Jersey to parse the following JSON:
{"response":{"status":"OK","campaigns":[{"id":12345,"state":"active","code":null}]}}
But I get the following error message:
java.lang.IllegalArgumentException: No more parsing elements.
If I switch the position of the fields code and state so that the resulting JSON looks like
{"response":{"status":"OK","campaigns":[{"id":12345,"code":null,"state":"active"}]}}
everything works fine. Also if I change the code-field in the first JSON to a non-null value like "code":"test", Jersey can parse this without any problems. I tried other more complex examples always getting the above mentioned error message when leaving the last field of any element of an array null.
I think I am doing something wrong, because I could not find any others having the similar problem. I already tried to implement a CustomJAXBContextResolver using other JSON notations like natural but nothing worked for me.
Any ideas?
Here are my binding classes:
#XmlRootElement
public class LoadEntityResponse {
public LoadEntityResponse() {
}
private Response response;
public Response getResponse() {
return response;
}
public void setResponse(Response response) {
this.response = response;
}
}
and
public class Response {
public Response() {
}
private String status;
private String error;
private String error_id;
private Campaign[] campaigns;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getError_id() {
return error_id;
}
public void setError_id(String error_id) {
this.error_id = error_id;
}
public Campaign[] getCampaigns() {
return campaigns;
}
public void setCampaigns(Campaign[] campaigns) {
this.campaigns = campaigns;
}
}
and finally
public class Campaign{
public Campaign() {
}
protected int id;
protected String code;
protected String state;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
Solved: Using JacksonJsonProvider now:
...
DefaultClientConfig config = new DefaultClientConfig();
config.getClasses().add(JacksonJsonProvider.class);
...
that´s all!
You can also use Jackson POJO support that comes with jersey-json but there is a need to do some configuration, see POJO support in Jersey User Guide.
Try using Genson http://code.google.com/p/genson/.
To enable it on client side use the following code:
ClientConfig config = new DefaultClientConfig();
config.getClasses().add(GensonJsonConverter.class);
cli = Client.create(config);
EDIT: on server side there is no configuration needed, when the jar is in your classpath json support is automatically enabled.
Currently I am trying to create a webservice which simply returns a list;
#Path("/random")
#Singleton
public class Random
{
#GET
#Path("/")
#Produces(MediaType.APPLICATION_JSON)
public MyResult<String> test()
{
MyResult<String> test = new MyResult<String>();
test.add("Awesome");
return test;
}
}
And my MyResult class looks like this:
#XmlRootElement
public class MyResult<T> implements Iterable<T>
{
private ArrayList<T> _items;
private int _total;
public MyResult()
{
_items = new ArrayList<T>();
}
public ArrayList<T> getItems()
{
return _items;
}
public void setItems(ArrayList<T> items)
{
_items = items;
}
public int getTotal()
{
return _total;
}
public void setTotal(int total)
{
_total = total;
}
public void add(T item)
{
getItems().add(item);
}
public Iterator<T> iterator()
{
return getItems().iterator();
}
}
Now I get the following result from the service:
{"items":[{"#type":"xs:string","$":"Awesome"}],"total":"0"}
But I don't want any of this information, I just require this:
{"items":["Awesome"],"total":"0"}
It seems to me this requires some configuration somewhere, who know how to get the required result?
Assuming you are using jackson, take a look at #JsonTypeInfo annotation. It is used for configuring details of if and how type information is used with JSON serialization and deserialization. The use and behaviour of it would depend on the version of jackson you are using.
To completely suppress type information, I had to use the following annotations:
#JsonTypeInfo(use=JsonTypeInfo.Id.NONE)
#JsonDeserialize(as=NoType.class)