nested json parsing for android with jackson - android

i just started to android prograamming and found nice tutorial by using imdb api. instead of using xml in this tutorial i would like to use json and for the recevied json i have a problem.
this is the person.json:
[
{
"score":1,
"popularity":3,
"name":"Brad Pitt",
"id":287,
"biography":"test",
"url":"http://www.themoviedb.org/person/287",
"profile":[
{
"image":{
"type":"profile",
"size":"thumb",
"height":68,
"width":45,
"url":"http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w45/w8zJQuN7tzlm6FY9mfGKihxp3Cb.jpg",
"id":"4ea5cb8c2c0588394800006f"
}
},
{
"image":{
"type":"profile",
"size":"profile",
"height":281,
"width":185,
"url":"http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185/w8zJQuN7tzlm6FY9mfGKihxp3Cb.jpg",
"id":"4ea5cb8c2c0588394800006f"
}
},
{
"image":{
"type":"profile",
"size":"h632",
"height":632,
"width":416,
"url":"http://d3gtl9l2a4fn1j.cloudfront.net/t/p/h632/w8zJQuN7tzlm6FY9mfGKihxp3Cb.jpg",
"id":"4ea5cb8c2c0588394800006f"
}
},
{
"image":{
"type":"profile",
"size":"original",
"height":1969,
"width":1295,
"url":"http://d3gtl9l2a4fn1j.cloudfront.net/t/p/original/w8zJQuN7tzlm6FY9mfGKihxp3Cb.jpg",
"id":"4ea5cb8c2c0588394800006f"
}
}
],
"version":685,
"last_modified_at":"2013-02-16 07:11:15 UTC"
}
]
my two object for them:
public class Person implements Serializable {
private static final long serialVersionUID = 6794898677027141412L;
public String score;
public String popularity;
public String name;
public String id;
public String biography;
public String url;
public String version;
public String lastModifiedAt;
public Profile profile;
}
public class Profile implements Serializable {
private static final long serialVersionUID = -8735669377345509929L;
public ArrayList<Image> imagesList;
}
public class Image implements Serializable {
private static final long serialVersionUID = -2428562977284114465L;
public String type;
public String url;
public String size;
public int width;
public int height;
}
ı couldnt figure out how to retrieve person list by using jackson object mapper.
when i use this one:
ObjectMapper mapper = new ObjectMapper();
Person person= mapper.readValue(jsonResponseString, Person.class);
i got:
02-16 18:34:48.010: W/System.err(376): com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.example.imdbsearcher.model.Person out of START_ARRAY token
02-16 18:34:48.180: W/System.err(376): at [Source: java.io.StringReader#40a81778; line: 1, column: 1]
02-16 18:34:48.554: W/System.err(376): at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:599)
02-16 18:34:48.830: W/System.err(376): at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:593)
i have changed the retrieve method with advice of Keith and crdnilfan.
but now i have a problem with the attribute of profile.
i realized that i am missing that one in person object and basicly i have created new profile object and moved imageList to this class.
i have updated POJO's as above.
but now i am getting the same error for the profile.
Can not deserialize instance of com.example.imdbsearcher.model.Profile out of START_ARRAY token

You need to deserialize the list, as your JSON is an array:
List<Person> people = mapper.readValue(
jsonResponseString, new TypeReference<List<Person >>(){});
However, after you do that you will have some additional deserialization errors because of the profile property in your JSON. Checkout: http://jackson.codehaus.org/1.5.7/javadoc/org/codehaus/jackson/annotate/JsonIgnoreProperties.html
Update:
public class Person implements Serializable
{
public List<Object> profile;
public String score;
public String popularity;
public String name;
public String id;
public String biography;
public String url;
public String version;
public String last_modified_at;
}
There are several ways to deal with this. This will give you a linked hash map for Profile.
Alternatively, if you control the JSON format, change the profile syntax to this:
"profile":[
image:...,
image:...
]

That's because you are trying to deserialize a list of Person.class, not one instance. Create another class like this
public class PersonList extends ArrayList<Person> {}
and then use
ArrayList<Person> people = mapper.readValue(jsonResponseString, PersonList.class);

The other two answers clearly explain the reason for the error, it would get rid off the error and it will parse Person object. But for me it failed to parse image objects. With below POJO we can parse the specified json completely, without any issues even in the absence of
#JsonIgnoreProperties
or
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
POJO definition:
public class PersonList extends ArrayList<Person> {}
public class Person implements Serializable {
private static final long serialVersionUID = 6794898677027141412L;
public String score;
public String popularity;
public String name;
public String id;
public String biography;
public String url;
public String version;
#JsonProperty(value="last_modified_at")
public String lastModifiedAt;
public List<Profile> profile;
}
public class Profile implements Serializable {
private static final long serialVersionUID = -8735669377345509929L;
#JsonProperty(value="image")
public Image imagesList;
}
public class Image implements Serializable {
private static final long serialVersionUID = -2428562977284114465L;
public String id;
public String type;
public String url;
public String size;
public int width;
public int height;
}
This should parse the json
String jsonResponseString = readJsonFile("person.json");
ObjectMapper mapper = new ObjectMapper();
PersonList person= mapper.readValue(jsonResponseString, PersonList.class);
or
List<Person> person= mapper.readValue(jsonResponseString,
new TypeReference<List< Person>>(){}); //if we use this we dont have to define PersonList class

Related

How to Save Foreign Keys in Room Database

I have the following Model class that i want to store in Room Database:
I don't know much but i think i need to use foreign key here. Though i dont have much idea, its just a guess.
If you can give a detailed explanation,
public class EarthquakeData {
public List < Feature > features;
public class Feature {
public String type;
public Properties properties;
// public Geometry geometry;
public String id;
public class Properties {
public double mag;
public String place;
public Object time;
public Object updated;
public Object tz;
public String url;
public String detail;
public int felt;
public double cdi;
public double mmi;
public String alert;
public String status;
public int tsunami;
public int sig;
public String net;
public String code;
public String ids;
public String sources;
public String types;
public int nst;
public double dmin;
public double rms;
public double gap;
public String magType;
public String type;
public String title;
}
}
}
I have saved only a simple class in Room database like the following class:
#Entity(tableName = "notes")
public class Note {
#PrimaryKey
#NonNull
private String id;
#NonNull
#ColumnInfo(name = "note")
private String mNote;
public Note(#NonNull String id, #NonNull String mNote) {
this.id = id;
this.mNote = mNote;
}
#NonNull
public String getId() {
return id;
}
#NonNull
public String getNote() {
return this.mNote;
}
}
But i don't know to save the first type of model class in Room which is very complex for me because it consists of objects within a class.
From what I understand you have the following relationships:
1 EarthquakeData - Many Features
and
1 Feature - 1 Properties
So you could model it this way:
Table Features(id: PrimaryKey, earthquake_data_id: ForeignKey, ...)
and
Table Feature(id: PrimaryKey, properties_id: ForeignKey, ...)
With Room entities this would look something like this for the features:
#Entity(
tableName = "features",
foreignKeys = [
ForeignKey(
entity = EarthquakeDataEntity::class,
parentColumns = ["id"],
childColumns = ["earthquake_data_id"],
onDelete = ForeignKey.CASCADE, // See documentation for other operations
onUpdate = ForeignKey.CASCADE
)
]
class Features {
...
}
Check out the ForeignKey official documentation for the parameters

Serialise / deserialise model in firestore

I have the following class that I want to store in firestore.
public class User extends Model {
#PropertyName("user_auth_id")
public String authUid;
#PropertyName("first_name")
public String firstName;
#PropertyName("last_name")
public String lastName;
#PropertyName("picture_url")
public String pictureUrl;
#PropertyName("email")
public String email;
#PropertyName("companies")
public ArrayList<UserCompany> companies;
public User() {}
}
public class UserCompany extends Model {
public String name;
public String role;
public String position;
public UserCompany() {
super();
}
public UserCompany(Company company, String role, String position) {
this();
name = company.name;
this.role = role;
this.position = position;
}
public Map<String, Object> toObject() {
Map<String, Object> object = new HashMap<>();
object.put("id", id);
object.put("name", name);
object.put("role", role);
object.put("position", position);
return object;
}
}
#IgnoreExtraProperties
public class Model {
#Exclude
public String id;
public <T extends Model> T withId(#NonNull final String id) {
this.id = id;
return (T) this;
}
}
And I want to use a transaction to update an user entry with it's newly created company list. (appUser instanceOf User)
transaction.update(userRef, "companies", appUser.companies);
If I do so...I get
Invalid data. Unsupported type: ro.exemple.model.UserCompany
How can I serialise an User object so that I can deserialise it as such
User appUser = queryDocumentSnapshots.getDocuments().get(0).toObject(User.class);
Where queryDocumentSnapshots is the result of a query in my firestore db.
I know I can change from ArrayList to HashMap, but I wish to keep the List, and try to serialise and deserialise it, in order to obtain in firestore an array of objects.
if this serialization you must tag your class as Serializable..
public UserCompany extends Model implements Serializable
public class User extends Model implements Serializable
plus tag the class Model as well

Save a List of custom object in savedInstanceState

I am currently building an app to retrieve information for a remote server. the data received are JSON and I am build a list of Data using the class below :
public class RedditData {
private RedditTopic data;
public RedditTopic getData() {
return data;
}
}
and RedditTopic class is defined as below:
public final class RedditTopic {
private static final String TAG = RedditTopic.class.getSimpleName();
private String author;
private String thumbnail;
private String title;
private String num_comments;
private long created_utc;
private String data;
private String name;
public RedditTopic(){};
public String getData() {
return data;
}
public String getAuthor() {
return author;
}
public String getThumbnail(){
return thumbnail;
}
public String getTitle(){
return title;
}
public String getComments(){
return num_comments + " comments";
}
public long getCreated_utc(){
return created_utc;
}
public String getRedditName(){
return name;
}
}
both of these classes are used to translate a JSON into an Object formatted data.
I do not want to really change them to make them Parceable to avoid impacting the extraction of JSON.
I have added :
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
Log.d(TAG, ">>>>>>>>>>>>>>>>>>>>>>>> SAVE");
savedInstanceState.putParcelableArrayList("RedditList", myListOfData );
super.onSaveInstanceState(savedInstanceState);
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, ">>>>>>>>>>>>>>>>>>>>>>>> RESTORE");
List<RedditData> myListOfData = savedInstanceState.getParcelableArrayList("RedditList");
}
Android complain because I need to implement Parceable in my class RedditData and I assume probably in the RedditTopic Class as well because RedditData returned a List of RedditTopic.
Is there a better way to do it? keep the List as I have it without requiring the Parceable option.
I do not have a List of String, it's a list of object.
Any idea?
Regards
Make your model objects parcleable.
There is a great extension, https://plugins.jetbrains.com/plugin/7332-android-parcelable-code-generator that will generate the neccesary parcelable methods for your class.
I highly recommend it.

How to deserialize to arraylist with annotations

I need deserialize a string(json) to a arraylist inside a model. I'm using the Jackson-Annotation library to do this. Anyone can help me?
I've tried this, but doesn't work:
#JsonDeserialize(as = Model.class)
private ArrayList<Model> model;
or:
#JsonDeserialize(as = ArrayModel.class) //ArrayModel extends arrayList<Model>
private ArrayList<Model> model;
Sample:
public class Model extends BaseModel {
#JsonProperty("id")
private int id;
#JsonDeserialize(as = ModelTwo.class)
private ArrayList<ModelTwo> modelTwo;
public ArrayList<ModelTwo> getModelTwo() {
return modelTwo;
}
public void setModelTwo(ArrayList<ModelTwo> modelTwo) {
this.modelTwo = modelTwo;
}
}
I've solved this!
You need say the type of Object and the type of content.
After this, you need create a new Json with properties on params.
On first model:
#JsonProperty("property")
#JsonDeserialize(as=ArrayList.class, contentAs=ModelTwo.class)
private List<ModelTwo> modelsTwo;
On second model:
#JsonCreator
public ModelTwo(
#JsonProperty("id") int id,
#JsonProperty("name") String name) {
this.id = id;
this.name = name;
}

Parsing URL using GSON

I just tried to parse the given URL using GSON but I get some problems.
The url
http://api.flickr.com/services/feeds/photos_public.gne?format=json
jsonFlickrFeed({
"title": "Uploads from everyone",
"link": "http://www.flickr.com/photos/",
.....)
The Json response is some thing like this . which contains a ({ in the begning of string which make problem in parsing.
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1
My model class is below like this:
public class Flicker {
public JsonFlickrFeed jsonFlickrFeed;
public JsonFlickrFeed getDealList() {
return jsonFlickrFeed;
}
public static class JsonFlickrFeed{
public String title;
public String link;
public String description;
public String modified;
public String generator;
public List<Items> items = new ArrayList<Flicker.Items>();
}
public static class Items {
public String title;
public String link;
public String media;
public String date_taken;
public String description;
public String published;
public String author;
public String author_id;
public String tags;
}
}
Take a look on Json and you can see that media is class:
"media": {"m":"http://farm4.staticflickr.com/3706/10153214694_177e2dcd6d_m.jpg"},
Therefore I added new class Media with String m;
BTW, you don't need to initiate List<Items> items = new ArrayList<Flicker.Items>();
Gson does that for you and convert any List to LinkedList
Here is a working code with fix:
Launcher
str = str.substring("jsonFlickrFeed(".length(), str.length()-1);
Gson gson = new Gson();
System.out.println(str);
JsonFlickrFeed jj = gson.fromJson(str, JsonFlickrFeed.class);
System.out.println((jj != null)?"true":"false");
Media
public class Media {
public String m;
}
JsonFlickrFeed
public class JsonFlickrFeed {
public String title;
public String link;
public String description;
public String modified;
public String generator;
public List<Items> items;
}
Items
public class Items {
public String title;
public String link;
public Media media;
public String date_taken;
public String description;
public String published;
public String author;
public String author_id;
public String tags;
}

Categories

Resources