Simple json structure throwing error when converting to pojo - java

I am attempting to convert a json String to a java pojo but receive this error when parsing :
org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type, class com.json.pojo.Userdatum] from JSON String; no single-String constructor/factory method
at org.codehaus.jackson.map.deser.std.StdValueInstantiator._createFromStringFallbacks(StdValueInstantiator.java:379)
at org.codehaus.jackson.map.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:268)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromString(BeanDeserializer.java:765)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:585)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2732)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1863)
at com.json.pojo.ParseJson.main(ParseJson.java:21)
here is my conversion code :
package com.json.pojo;
import java.io.IOException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
public class ParseJson {
public static void main(String args[]){
String str = "\"userdata\": [ {\"userid\": \"user1\",\"title\": \"Next weeks preview\", \"date\": \"19/12/2013\",\"time\": \"15:00\"}";
org.codehaus.jackson.map.ObjectMapper mapper = new org.codehaus.jackson.map.ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
com.json.pojo.Userdatum user = mapper.readValue(str, com.json.pojo.Userdatum.class);
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And my pojo :
package com.json.pojo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Generated;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#Generated("com.googlecode.jsonschema2pojo")
#JsonPropertyOrder({
"userdata"
})
public class UserData {
#JsonProperty("userdata")
private List<Userdatum> userdata = new ArrayList<Userdatum>();
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("userdata")
public List<Userdatum> getUserdata() {
return userdata;
}
#JsonProperty("userdata")
public void setUserdata(List<Userdatum> userdata) {
this.userdata = userdata;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperties(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
package com.json.pojo;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Generated;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#Generated("com.googlecode.jsonschema2pojo")
#JsonPropertyOrder({
"userid",
"title",
"date",
"time"
})
public class Userdatum {
#JsonProperty("userid")
private String userid;
#JsonProperty("title")
private String title;
#JsonProperty("date")
private String date;
#JsonProperty("time")
private String time;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("userid")
public String getUserid() {
return userid;
}
#JsonProperty("userid")
public void setUserid(String userid) {
this.userid = userid;
}
#JsonProperty("title")
public String getTitle() {
return title;
}
#JsonProperty("title")
public void setTitle(String title) {
this.title = title;
}
#JsonProperty("date")
public String getDate() {
return date;
}
#JsonProperty("date")
public void setDate(String date) {
this.date = date;
}
#JsonProperty("time")
public String getTime() {
return time;
}
#JsonProperty("time")
public void setTime(String time) {
this.time = time;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperties(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
There must be something wrong with the generated pojo but it looks correct ?

This works, for some reason I needed to use the #JsonProperty even though my properties are matching the json attributes, I did'nt think they were required.
package com.json.pojo;
import java.io.IOException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
public class ParseJson {
public static void main(String args[]){
String str = "{ \"userdata\": [ {\"userid\": \"user1\",\"title\": \"Next weeks preview\", \"date\": \"19/12/2013\",\"time\": \"15:00\"} ] }";
org.codehaus.jackson.map.ObjectMapper mapper = new org.codehaus.jackson.map.ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true);
try {
com.json.pojo.RequestBean user = mapper.readValue(str, com.json.pojo.RequestBean.class);
System.out.println(user.getToAdd().size());
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package com.json.pojo;
import java.io.Serializable;
import java.util.List;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonSerialize;
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
public class RequestBean implements Serializable {
#JsonProperty("userdata")
private List<SimpleBean> userdata;
public List<SimpleBean> getToAdd() {
return userdata;
}
public void setToAdd(List<SimpleBean> toAdd) {
this.userdata = toAdd;
}
// constructors, getters, setters
}
package com.json.pojo;
import java.io.Serializable;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonSerialize;
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
public class SimpleBean implements Serializable {
#JsonProperty("userid")
private String userid;
#JsonProperty("title")
private String title;
#JsonProperty("date")
private String date;
#JsonProperty("time")
private String time;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}

Related

Error when trying to map foreing key in SpringBoot

I'm trying to create an API for saving a Person and its Address, like in this model:
And i'm getting this error when trying to save an address with a foreing key:
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error:
Cannot construct instance of `com.apitest.api.model.Pessoa` (although at least one Creator exists):
no int/Int-argument constructor/factory method to deserialize from Number value (1)]
I know it seems like a parser error, but it just happens when i do a request that contains the fk field, so:
This is a valid request:
{
"logradouro": "test",
"cep": "354",
"numero": "test",
"cidade": "test"
}
This one i get a 400 bad request:
{
"logradouro": "null",
"cep": "354",
"numero": "null",
"cidade": "null",
"pessoa": 1
}
Just by adding the fk field, like i said.
Models:
Person
package com.apitest.api.model;
import java.util.Date;
import java.util.List;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
#Entity
#Table(name = "pessoa")
public class Pessoa {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name = "nome")
private String nome;
#Column(name = "dataNascimento")
private Date dataNascimento;
public Pessoa(Integer id, String nome, Date dataNascimento) {
this.id = id;
this.nome = nome;
this.dataNascimento = dataNascimento;
}
public Pessoa(){
};
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Date getDataNascimento() {
return dataNascimento;
}
public void setDataNascimento(Date dataNascimento) {
this.dataNascimento = dataNascimento;
}
}
Address
package com.apitest.api.model;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
#Entity
#Table(name = "endereco")
public class Endereco {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id_endereco;
#Column(name = "logradouro")
private String logradouro;
#Column(name = "cep")
private String cep;
#Column(name = "numero")
private String numero;
#Column(name = "cidade")
private String cidade;
#ManyToOne
#JoinColumn(name = "id")
private Pessoa pessoa;
public Endereco(Integer id_endereco, String logradouro, String cep, String numero, String cidade, Pessoa pessoa) {
this.id_endereco = id_endereco;
this.logradouro = logradouro;
this.cep = cep;
this.numero = numero;
this.cidade = cidade;
this.pessoa = pessoa;
}
public Endereco(){
};
public String getLogradouro() {
return logradouro;
}
public void setLogradouro(String logradouro) {
this.logradouro = logradouro;
}
public String getCep() {
return cep;
}
public void setCep(String cep) {
this.cep = cep;
}
public String getNumero() {
return numero;
}
public void setNumero(String numero) {
this.numero = numero;
}
public String getCidade() {
return cidade;
}
public void setCidade(String cidade) {
this.cidade = cidade;
}
public Pessoa getPessoa() {
return pessoa;
}
public void setPessoa(Pessoa pessoa) {
this.pessoa = pessoa;
}
public Integer getId_endereco() {
return id_endereco;
}
public void setId_endereco(Integer id_endereco) {
this.id_endereco = id_endereco;
}
}
Controllers:
Person
package com.apitest.api.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.apitest.api.model.Pessoa;
import com.apitest.api.service.PessoaService;
#RestController
public class PessoaController {
#Autowired
private PessoaService pessoaService;
#PostMapping("/pessoas")
public ResponseEntity<Pessoa> createPessoa(#RequestBody Pessoa pessoa){
return ResponseEntity.ok().body(this.pessoaService.createPessoa(pessoa));
}
}
Address
package com.apitest.api.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.apitest.api.model.Endereco;
import com.apitest.api.service.EnderecoService;
#RestController
public class EnderecoController {
#Autowired
private EnderecoService enderecoService;
#PostMapping("/endereco")
public ResponseEntity<Endereco> createEndereco(#RequestBody Endereco endereco){
return ResponseEntity.ok().body(this.enderecoService.createEndereco(endereco));
}
}
Service:
Person
package com.apitest.api.service;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.apitest.api.model.Pessoa;
import com.apitest.api.repository.PessoaRepository;
#Service
#Transactional
public class PessoaServiceImpl implements PessoaService {
#Autowired
private PessoaRepository pessoaRepository;
#Override
public Pessoa createPessoa(Pessoa pessoa) {
return pessoaRepository.save(pessoa);
}
#Override
public Pessoa updatePessoa(Pessoa pessoa) {
Optional<Pessoa> pessoaDb = this.pessoaRepository.findById(pessoa.getId());
Pessoa pessoaUpdate = pessoaDb.get();
pessoaUpdate.setId(pessoa.getId());
pessoaUpdate.setNome(pessoa.getNome());
return pessoaUpdate;
}
#Override
public Pessoa getPessoaById(Pessoa pessoa) {
// TODO Auto-generated method stub
return null;
}
#Override
public List<Pessoa> getAllPessoa() {
// TODO Auto-generated method stub
return null;
}
#Override
public void deletePessoa(long pessoaId) {
// TODO Auto-generated method stub
}
}
Address
package com.apitest.api.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.apitest.api.model.Endereco;
import com.apitest.api.repository.EnderecoRepository;
import com.apitest.api.repository.PessoaRepository;
import org.springframework.transaction.annotation.Transactional;
#Service
#Transactional
public class EnderecoServiceImpl implements EnderecoService {
#Autowired
private EnderecoRepository enderecoRepository;
#Override
public Endereco createEndereco(Endereco endereco) {
return enderecoRepository.save(endereco);
}
}
I have already tried to use JsonCreator and JsonProperty annotations but did not worked for me...
Any help would be appreciated.
You're getting this error because you're sending the value of "1" for the object Pessoa. You need to pass the fields in the object, something like this should work.
{ "logradouro": "null", "cep": "354", "numero": "null", "cidade": "null", "pessoa": {"id": 1} }
Also, I'm not sure what "null" means here, but if you want those fields to be null, don't send them. The way this is written, you're going to end up with the word null everywhere.

Getting Date as null when using java.sql.Date

I am trying to insert the date into database and I am using java.sql.Date but the problem when user is submitting the form I am getting Null value. As per some restriction I am only allowed to use java.sql.Date not util.Date.
Entity
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
#Entity
#Table(name="Users")
public class Users {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="User_ID")
private int ID;
#Column(name="User_first_name")
#NotEmpty(message="Field cannot be left blank")
private String First_Name;
#Column(name="user_last_name")
private String Last_Name;
#Column(name="user_contact")
private int Contact;
#Column(name="user_email")
private String Email;
#Column(name="user_date_birth")
#DateTimeFormat(pattern="dd/MM/yyyy")
private Date DateOfBirth;
#Column(name="user_joining_date")
private Date DateOfJoining;
#Column(name="user_salary")
#NotNull
private int Salary;
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
public String getFirst_Name() {
return First_Name;
}
public void setFirst_Name(String first_Name) {
First_Name = first_Name;
}
public String getLast_Name() {
return Last_Name;
}
public void setLast_Name(String last_Name) {
Last_Name = last_Name;
}
public int getContact() {
return Contact;
}
public void setContact(int contact) {
Contact = contact;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public Date getDateOfBirth() {
return DateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
DateOfBirth = dateOfBirth;
}
public Date getDateOfJoining() {
return DateOfJoining;
}
public void setDateOfJoining(Date dateOfJoining) {
DateOfJoining = dateOfJoining;
}
public int getSalary() {
return Salary;
}
public void setSalary(int salary) {
Salary = salary;
}
}
Controller
package com.example.crud;
import java.text.SimpleDateFormat;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.example.crud.entities.Users;
import com.example.crud.service.TaskService;
#Controller
public class HomeController {
#Autowired
private TaskService service;
private Logger logger = LoggerFactory.getLogger(HomeController.class);
#InitBinder
public void initBinder(WebDataBinder binder){
System.out.println("exe");
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setLenient(true);
binder.registerCustomEditor(java.sql.Date.class,"DateOfBirth", new CustomDateEditor(sdf, true));
}
#RequestMapping(value="/Add", method=RequestMethod.GET)
public String index(Map<String, Object> model){
Users users = new Users();
model.put("users", users);
logger.debug("users");
return "home";
}
#RequestMapping(value="/Register", method=RequestMethod.POST)
public String Register(#ModelAttribute("users") Users users, BindingResult result, Model model){
System.out.println(users.getFirst_Name());
System.out.println(users.getDateOfBirth());
// service.Register(users);
return "home";
}
}
Register your own custom editor.
public class SqlDateEditor extends PropertyEditorSupport {
private DateFormat dateFormat;
public SqlDateEditor (final DateFormat dateFormat)
{
this.dateFormat = dateFormat;
}
#Override
public void setAsText(String text) {
try {
setValue(new java.sql.Date(this.dateformat.parse(text).getTime())
} catch (ParseException e) {
throw new IllegalArgumentException("Could not parse date: " + e.getMessage());
}
}
#Override
public String getAsText() {
java.sql.Date value = (java.sql.Date) getValue();
return (value != null ? this.dateFormat.format(value) : "");
}
}
At your controller:
#InitBinder
public void initBinder(final WebDataBinder binder) {
binder.registerCustomEditor(java.sql.Date.class, new SqlDateEditor(new SimpleDateFormat("dd/MM/yyyy")));
}

Creating multiple XML files from a hashmap in Java

I'm trying to create a XML file from a HashMap. For each key of the hash i want an XML file. The value of the key is an ArrayList of Objects. I am using JAXB but the XML files are not created, as the output is not XML valid.
The object class:
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "Product")
public class Product implements Comparable<Product>{
String ID,description, gtin;
double price;
String date;
Product()
{
}
public String toString()
{
return ID+" "+description+" "+gtin+" "+price+" "+date;
}
public String getID() {
return ID;
}
#XmlElement
public void setID(String ID) {
this.ID = ID;
}
public String getDescription() {
return description;
}
#XmlElement
public void setDescription(String description) {
this.description = description;
}
public String getGtin() {
return gtin;
}
#XmlElement
public void setGtin(String gtin) {
this.gtin = gtin;
}
public double getPrice() {
return price;
}
#XmlElement
public void setPrice(Double price) {
this.price = price;
}
}
The class where i try to create the XMLs:
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class CreateXML {
static void create(HashMap<String, ArrayList<Product> > map) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(ProdsList.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Set setOfKeys = map.keySet();
Iterator iterator = setOfKeys.iterator();
while (iterator.hasNext()) {
String keys = (String) iterator.next();
String filename= "C:\\Users\\As\\Desktop\\Sups\\"+keys+22+".xml";
File file = new File(filename);
ArrayList<Product> value = map.get(keys);
jaxbMarshaller.marshal(value, file);
jaxbMarshaller.marshal(value, System.out);
}
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
The class for the root of the xml:
import java.util.*;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
//#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name="Products")
//#XmlSeeAlso({ArrayList.class})
class ProdsList {
#XmlElement(name="Product")
ArrayList<Product> prods;
public ProdsList(){
prods=new ArrayList<Product>();
}
public ArrayList<Product> getProducts() {
return prods;
}
public void setProducts(ArrayList<Product> prods) {
this.prods = prods;
}
}
How can i fix this. Thanks in advance.
You need to marshal an instance of ProdsList. Instead you are trying to marshall
an ArrayList of Products.
Change
jaxbMarshaller.marshal(value, file);
jaxbMarshaller.marshal(value, System.out);
To
jaxbMarshaller.marshal(new ProdsList(value), file);
jaxbMarshaller.marshal(new ProdsList(value), System.out);

jackson List of subclasses deserialisation

I am working on a webservice where i am supposed to provide xml as response, I am using jackson for that. I am stuck at an issue, I have an abstract class:
package com.spinner.jackson;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;
public class ClientObject {
#JacksonXmlElementWrapper(useWrapping = false)
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
private List<MyItem> accounts;
public ClientObject(List<MyItem> pl) {
this.accounts = pl;
}
public ClientObject() {
this.accounts = new ArrayList<MyItem>();
}
#JsonDeserialize(using = CustomDeserial.class)
public void setL(List<MyItem> l) {
this.accounts = l;
}
public List<MyItem> getAccounts() {
// TODO Auto-generated method stub
return this.accounts;
}
}
and then I have sub classes as follow:
package com.spinner.jackson;
import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
#JacksonXmlRootElement(localName="itemA")
public class MySubItemA extends MyItem {
public MySubItemA() {
super();
// TODO Auto-generated constructor stub
}
public MySubItemA(int id, String name) {
super(id, name);
// TODO Auto-generated constructor stub
}
private String itemAProperty1;
private String itemAProperty2;
public String getItemAProperty1() {
return this.itemAProperty1;
}
public void setItemAProperty1(String itemAProperty1) {
this.itemAProperty1 = itemAProperty1;
}
public String getItemAProperty2() {
return this.itemAProperty2;
}
public void setItemAProperty2(String itemAProperty2) {
this.itemAProperty2 = itemAProperty2;
}
#JsonCreator
public MySubItemA(#JsonProperty("id")int id, #JsonProperty("name")String name, #JsonProperty("itemAProperty1")String p1, #JsonProperty("itemAProperty2")String p2) {
super(id, name);
this.itemAProperty1 = p1;
this.itemAProperty2 = p2;
}
}
another sub class
package com.spinner.jackson;
import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
#JacksonXmlRootElement(localName="itemB")
public class MySubItemB extends MyItem {
private int itemBProperty1;
private String itemBProperty2;
public int getItemBProperty1() {
return this.itemBProperty1;
}
public void setItemBProperty1(int itemBProperty1) {
this.itemBProperty1 = itemBProperty1;
}
public String getItemBProperty2() {
return this.itemBProperty2;
}
public void setItemBProperty2(String itemBProperty2) {
this.itemBProperty2 = itemBProperty2;
}
public MySubItemB(#JsonProperty("id")int id, #JsonProperty("name")String name, #JsonProperty("itemBProperty1")int p1, #JsonProperty("itemBProperty2")String p2) {
super(id, name);
this.itemBProperty1 = p1;
this.itemBProperty2 = p2;
}
}
and a client class as followed:
package com.spinner.jackson;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;
public class ClientObject {
#JacksonXmlElementWrapper(useWrapping = false)
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
private List<MyItem> accounts;
public ClientObject(List<MyItem> pl) {
this.accounts = pl;
}
public ClientObject() {
this.accounts = new ArrayList<MyItem>();
}
#JsonDeserialize(using = CustomDeserial.class)
public void setL(List<MyItem> l) {
this.accounts = l;
}
#JsonDeserialize(using = CustomDeserial.class)
public List<MyItem> getAccounts() {
// TODO Auto-generated method stub
return this.accounts;
}
}
MyItem Class:
package com.spinner.jackson;
import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
#XmlRootElement
public abstract class MyItem {
public MyItem() {
super();
// TODO Auto-generated constructor stub
}
private int id;
private String name;
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public MyItem(int id, String name) {
this.id = id;
this.name = name;
}
}
above generate output xml as followed
<ClientObject>
<accounts>
<MySubItemA>
....
</MySubItemA>
</accounts>
<accounts>
<MySubItemB>
....
</MySubItemB>
</accounts>
</ClientObject>
is there a way to remove <accounts> wrapper even though I am using #JacksonXmlElementWrapper(useWrapping = false), also if I remove this annotation it does something as followed
<ClientObject>
<accounts>
<accounts>
<MySubItemA>
....
</MySubItemA>
</accounts>
<accounts>
<MySubItemB>
.....
</MySubItemB>
</accounts>
</accounts>
</ClientObject>
so final output should be
<ClientObject>
<MySubItemA>
....
</MySubItemA>
<MySubItemB>
....
</MySubItemB>
</ClientObject>
thanks for your help.
Best regards
Sajid
I was able to figure it out so I think it may help someone else:
I created Serializer
package com.spinner.jackson;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class MySerial extends JsonSerializer<ClientObject>
{
public void serialize(ClientObject value, JsonGenerator jgen,
SerializerProvider provider)
throws IOException, JsonProcessingException
{
jgen.writeObjectFieldStart(value.getClass().getSimpleName());
jgen.writeObjectField(value.getAccounts().get(0).getClass().getSimpleName(), value.getAccounts().get(0));
jgen.writeObjectField(value.getAccounts().get(1).getClass().getSimpleName(), value.getAccounts().get(1));
jgen.writeObjectField(value.getAccounts().get(2).getClass().getSimpleName(), value.getAccounts().get(2));
jgen.writeObjectField(value.getAccounts().get(3).getClass().getSimpleName(), value.getAccounts().get(3));
}
}
and next I did following in ClientObject.java:
package com.spinner.jackson;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
#JsonSerialize(using = CustomDeserial.class)
public class ClientObject {
#JacksonXmlElementWrapper(useWrapping = false)
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
private List<MyItem> accounts;
public ClientObject(List<MyItem> pl) {
this.accounts = pl;
}
public ClientObject() {
this.accounts = new ArrayList<MyItem>();
}
public void setL(List<MyItem> l) {
this.accounts = l;
}
public List<MyItem> getAccounts() {
return this.accounts;
}
}
and voila it worked, hope this helps some one.

Unable to fetch json object and array in Retrofit 2

I'm trying to parse the json from the api http://badiyajobs.com/apis/v1/rolesbut response.isSuccess is returning false
my modal class is,
package arpit.retrodemo;
import java.util.List;
import java.util.ArrayList;
public class Modal {
private List<RolesEntity> roles = new ArrayList<>();
public void setRoles(List<RolesEntity> roles) {
this.roles = roles;
}
public List<RolesEntity> getRoles() {
return roles;
}
public static class RolesEntity {
private String id;
private String role;
private String description;
private String icon_url;
private String created_at;
private String updated_at;
public void setId(String id) {
this.id = id;
}
public void setRole(String role) {
this.role = role;
}
public void setDescription(String description) {
this.description = description;
}
public void setIcon_url(String icon_url) {
this.icon_url = icon_url;
}
public void setCreated_at(String created_at) {
this.created_at = created_at;
}
public void setUpdated_at(String updated_at) {
this.updated_at = updated_at;
}
public String getId() {
return id;
}
public String getRole() {
return role;
}
public String getDescription() {
return description;
}
public String getIcon_url() {
return icon_url;
}
public String getCreated_at() {
return created_at;
}
public String getUpdated_at() {
return updated_at;
}
}
}
Sample json is,
{"roles":[
{
"id":"1",
"role":"Retail Sales Executive",
"description":"As a sales assistant....",
"icon_url":"",
"created_at":"2015-10-02 12:03:03",
"updated_at":null
}
]
}
APIService.java is,
package arpit.retrodemo;
import retrofit.Call;
import retrofit.http.GET;
public interface APIService {
#GET("/roles")
Call<Modal> getDetails();
}
MainActivity.java is,
package arpit.retrodemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import retrofit.Call;
import retrofit.Callback;
import retrofit.GsonConverterFactory;
import retrofit.Response;
import retrofit.Retrofit;
public class MainActivity extends AppCompatActivity {
private static final String ENDPOINT = "http://badiyajobs.com/apis/v1";
private APIService service;
private Modal mod;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(ENDPOINT)
.build();
service = retrofit.create(APIService.class);
Call<Modal> userList = service.getDetails();
userList.enqueue(new Callback<Modal>() {
#Override
public void onResponse(Response<Modal> response) {
if(response.isSuccess()){
Log.d("findRes", response.body().toString());
}else{
Log.d("find", "Something is wrong! " + response.errorBody().toString());
}
}
#Override
public void onFailure(Throwable t) {
Log.d("findError", t.getMessage());
}
});
}
}
Here i'm getting the following on logcat,
D/find: Something is wrong! com.squareup.okhttp.ResponseBody$1#52715c98
instead of the string representation of response.body()
You need to do the following:
public interface APIService {
#GET("roles") /*removed the / here */
Call<Modal> getDetails();
}
private static final String ENDPOINT = "http://badiyajobs.com/apis/v1/"; /* added the / here */

Categories

Resources