I want to receive Json data from server using Retrofit.
Below is Data class and Json example.
After finish transfer the 'Page' object is returned from Response.body().
But inside it the array 'cards' has 'null' value.
How can I get the correct data?
[Page.java]===========
public class Page {
public List<Cards> cards;
public Page(List<Cards> cards) {
this.cards = cards;
}
public class Cards {
public String card_type;
public Cards(String card_type) {
this.card_type = card_type;
}
}
}
[Json example]===============
{
"page": {
"cards": [
{
"card_type": "text",
"card": {
"value": "Hello, Welcome to App!",
"attributes": {
"text_color": "#262626",
"font": {
"size": 30
}
}
}
},
{
"card_type": "title_description",
"card": {
"title": {
"value": "Check out our App every week for exciting offers.",
"attributes": {
"text_color": "#262626",
"font": {
"size": 24
}
}
},
"description": {
"value": "Offers available every week!",
"attributes": {
"text_color": "#262626",
"font": {
"size": 18
}
}
}
}
},
]
}
}
first of all your model class not have get methods , your methods are setter not getter and its normal you cant get data without getter method , change your model like below :
at first , do not use inner class , made classes separate together
public class Page {
public List<cards> cards;
public List<cards> getCards() {
return cards;
}
public class cards {
public String card_type;
public String getCard_type() {
return card_type;
}
public card card;
public card getCard() {
return card;
}
}
public class card {
public String value;
public String getValue() {
return value;
}
public attributes attributes;
public String getAttributes() {
return attributes;
}
}
now this classes correct for your index 0 of cards , but your Json sample not have organization at next index ... but you can made title class or description class and add it to card class for get more data from any index of your list.
Related
public class MyResponse {
private List<Data> data;
public static class Data {
private long id;
private String name;
}
}
Using Jackson this gets serialized to the following JSON:
{
"data": [
{
"id": 115125,
"name": "AAAY"
}
]
}
What I need instead is the JSON like this, i,e. omitting the wrapping Data class:
[
{
"id": 115125,
"name": "AAAY"
}
]
Place the #JsonValue annotation on the data field:
public class MyResponse {
#JsonValue
private List<Data> data;
...
}
I am trying to map the following JSON to my POJO using Jackson. I have the following JSON and following POJOs. kindly let me know how to map the JSON to POJO.
JSON string :
{
"Application": {
"id": "0",
"name": "MyApp",
"users": [
{
"User": {
"id": "2",
"name": "Beth Jones"
}
}
],
"groups": [
{
"Group": {
"id": "1",
"name": "SimpleGroup",
"users": [
{
"User": {
"id": "2",
"name": "Beth Jones"
}
}
]
}
}
]
}
}
The POJO according to the client specification is below :
package com.example.custom;
//import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.example.Application;
import com.example.Group;
import com.example.User;
import java.util.Collection;
//#JsonIgnoreProperties(ignoreUnknown = true)
public class MyApplication extends Application {
private Collection<User> users;
private Collection<Group> groups;
public MyApplication(String id, String name) {
super(id, name);
}
public void setUsers(Collection<User> users) {
this.users = users;
}
public void setGroups(Collection<Group> groups) {
this.groups = groups;
}
#Override
public Collection<User> getUsers() {
return this.users;
}
#Override
public User getUser(String userId) {
for (User user: MyParser.myApp.getUsers()) {
if (user.getId().equals(userId))
return user;
}
return null;
}
#Override
public Collection<Group> getGroups() {
return this.groups;
}
#Override
public Group getGroup(String groupId) {
for (Group group: MyParser.myApp.getGroups()) {
if (group.getId().equals(groupId))
return group;
}
return null;
}
#Override
public String toString() {
return "MyApplication{" +
"users=" + users +
", groups=" + groups +
'}';
}
}
Mapping Logic :
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MyParser.myApp = mapper.readValue(rewriter.getText(),MyApplication.class);
The resulting object is not able to capture anything as it is all null. Kindly help. Thanks in advance.
I think you should model your JSON correctly, In the users list you shouldn't specify it again that the key is User, that should be preassumed that a list of users will only contain user, same goes for groups list.
IMHO the JSON should look something like this :
{
"application": {
"id": "0",
"name": "MyApp",
"users": [ . ==> Since this is a user List, it will definitely contains user.
{
"id": "2",
"name": "Beth Jones"
}
],
"groups": [
{
"id": "1",
"name": "SimpleGroup",
"users": [
{
"id": "2",
"name": "Beth Jones"
}
]
}
]
}
}
Now the POJO also needs some modification, I am just adding the bare-minimum POJO.
class Application { <====== Top Level Class
private Long id;
private String name;
private List<User> users; // Application has some Users
private List<Group> groups; // Application has some groups
}
class User {
private Long id;
private String name;
}
class Group {
private Long id;
private String name;
private List<User> users; // Each group has some associated users.
}
Now you can use any standard JSON library for Java and convert your JSON into POJO. This will simplify your structure and you won't face null issues with this structure.
Similar question was asked here Serialize/Deserialize dynamic property name using JSON.NET. I am not able to make it work in my situation as below:
I have the following JSON
{
"notes": {
"data": [{
"book": {
"items": [{
"page": "page 1",
"comment": "Some notes"
},
{
"page": "page 1",
"comment": "Some notes"
}
]
}
},
{
"journal": {
"items": [{
"page": "page 1",
"comment": "Some notes"
},
{
"page": "page 1",
"comment": "Some notes"
}
]
}
},
{
"magazine": {
"items": [{
"page": "page 1",
"comment": "Some notes"
},
{
"page": "page 1",
"comment": "Some notes"
}
]
}
}
]
}
}
Created the following classes for JSON serialization:
public class TestParse
{
public Note Notes { get; set; }
}
public class Note
{
public IList<Data> Data { get; set; }
}
public class Data
{
public Source Source { get; set; }
}
[JsonConverter(typeof(MyConverter))]
public class Source
{
public IList<Items> Items { get; set; }
}
public class Items
{
public string Page { get; set; }
public string Comment { get; set; }
}
public class MyConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Source);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
var jo = JObject.Load(reader);
var req = new Data
{
Source = jo.ToObject<Source>()
};
return req;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var req = (Source)value;
var jo = new JObject(
new JObject(req.Items));
jo.WriteTo(writer);
}
}
}
I am still not able to deserialize "Source." Any pointer is appreciated.
In the other question you referenced, the dynamic key was determined by the value of another property in the same object. Hence, a converter was needed.
In your situation, you have dynamic keys, but they are not dependent on anything.
You don't really need a converter here; you can just use a Dictionary to handle the dynamic keys.
Change this line in your Note class:
public IList<Data> Data { get; set; }
to this:
public IList<IDictionary<string, Source>> Data { get; set; }
and remove the [JsonConverter] attribute from your Source class. Then it should work.
(You can also delete the Data class as it is not needed.)
Fiddle: https://dotnetfiddle.net/80lIRI
colleagues!
We want to write Rest Client to service which follow the HATEOAS principle. So we have the following HAL+JSON representation and we want to deserialize it using spring-hateoas :
{
"id": "1",
"title": "album title",
"artistId": "1",
"stockLevel": 2,
"_links": {
"self": {"href": "http://localhost:8080/rest/albums/1"},
"artist": {"href": "http://localhost:8080/rest/artist/1"}
},
"_embedded": {
"albums": [{ //can be array or object
"id": "1",
"title": "album title",
"artistId": "1",
"stockLevel": 2,
"_links": {
"self": {"href": "http://localhost:8080/rest/albums/1"}
}
}],
"artist": { //can be array or object
"id": "1",
"name": "artist name",
"_links": {
"self": {"href": "http://localhost:8080/rest/artist/1"}
}
} //....
}
}
We expected the java object like this:
HalResource {
Resource<Album> //entity
List<Link> // _links
List<Resource<BaseEntity>>{ //_embedded
Resource<Album>
Resource<Artist>
....
}
}
So we have custom resource representation with embedded(list of resources) and entity(single resource):
#XmlRootElement(name = "resource")
public class HalResource<EntityType, EmbeddedType> extends Resources<EmbeddedType> {
#JsonUnwrapped
private EntityType entity;
public HalResource() {
}
public HalResource(Iterable<EmbeddedType> content, Link... links) {
super(content, links);
}
public EntityType getEntity() {
return entity;
}
public void setEntity(EntityType entity) {
this.entity = entity;
}
}
DTO classes:
public abstract class BaseEntity{}
#XmlRootElement(name = "album")
public class Album extends BaseEntity {
private String id;
private String title;
private String artistId;
private int stockLevel;
// getters and setters...
}
#XmlRootElement(name = "artist")
public class Artist extends BaseEntity {
private String id;
private String name;
// getters and setters...
}
And we want to get something like this, where Entity will be Artist or Album, but HalResourcesDeserializer return Resource.class with null content.
HalResource<Album, Resource<Entity>> resources =
restClient.getRootTarget().path("albums/1").queryParam("embedded", true).request().accept("application/hal+json")
.get(new GenericType<HalResource<Album, Resource<Entity>>>() {});
By using #JsonTypeInfo and #JsonSubTypes anotations we successfully deserialized our JSON(you can see the example on the github), but we don't want to have some additional type filds and anotattions in our DTO and JSON format.
We see one solution that is create a custom deserializer which can processing that.
So the question is: What is the convenient way to deserialize our JSON(links + embedded container) using spring-hateoas?
We use spring-hateoas 0.16v(but we tried 0.19v) and glassfish jersey 2.22.1
Thank you!
I need to unmarshall JSON having array as a top-level element:
[
{
"test1":
{
"name": "Boost",
"fraction": 0.55
}
},
{
"test2":
{
"name": "Boost",
"fraction": 0.55
}
}
]
My top-level element looks like this:
import javax.xml.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
public class Wrapper<T> {
#XmlTransient
private List<T> items;
public Wrapper() {
items = new ArrayList<>();
}
public Wrapper(List<T> items) {
this.items = items;
}
#XmlElement
public List<T> getItems() {
return items;
}
}
Unmarshalling is done in this method:
private <T> T get(String path, Class<T> aClass) {
WebTarget target = root.path(path);
Invocation.Builder request = target.request(MediaType.APPLICATION_JSON_TYPE);
return request.get(aClass);
}
When I tried to marshall an existing object into json I have got the following result:
{
"items" : [
{
"test1":
{
"name": "Boost",
"fraction": 0.55
}
},
{
"test2":
{
"name": "Boost",
"fraction": 0.55
}
}
]}
How can I force JAXB to skip this items key?
Thanks for your help.
I solved the problem using GenericType new GenericType<List<MyObject>>() {}