I'm having trouble trying to deserialize a JSON string. I'm using gson
This is the class
public class Notebook {
public static String DESCRIPTION = "description";
#SerializedName("id") private long id;
#SerializedName("user_id") private long userId;
#SerializedName("description") private String description;
#SerializedName("created_at") private String railsCreated;
#SerializedName("updated_at") private String railsUpdated;
#SerializedName("created_android") private String androidCreated;
#SerializedName("updated_android") private String androidUpdated;
private List<Note> notes;
private boolean isUploaded = false;
/*constructors, getters, and setters */
public static void uploadNotebook(Notebook notebook) {
MultipartEntity entity = new MultipartEntity();
HttpResponse response;
Notebook updatedNotebook = new Notebook();
Gson gson = new Gson();
try {
StringBody description = new StringBody(notebook.getDescription());
StringBody user = new StringBody("1");
StringBody format = new StringBody("json");
// StringBody androidCreated = new StringBody(notebook.getAndroidCreated().toString());
// StringBody androidUpdated = new StringBody(notebook.getAndroidUpdated().toString());
entity.addPart("description", description);
entity.addPart("user_id", user);
entity.addPart("format", format);
// entity.addPart("android_created", androidCreated);
// entity.addPart("android_updated", androidUpdated);
response = WebService.postRequest(entity, WebService.POST_NOTEBOOK_URL);
String json = EntityUtils.toString(response.getEntity());
Log.i("Note Uploader", json);
updatedNotebook = gson.fromJson(json, Notebook.class);
if(updatedNotebook != null) {
Log.i("Notebook ID", ""+updatedNotebook.getId());
Log.i("Notebook userID", ""+updatedNotebook.getUserId());
Log.i("Notebook Title", ""+updatedNotebook.getDescription());
Log.i("Notebook CreatedAt", ""+updatedNotebook.getRailsCreated());
Log.i("Notebook UpdatedAt", ""+updatedNotebook.getRailsUpdated());
updatedNotebook.setUploaded(true);
}
} catch (UnsupportedEncodingException e) {
Log.i("Note Uploader", e.getMessage());
} catch (ClientProtocolException e) {
Log.i("Note Uploader", e.getMessage());
} catch (IOException e) {
Log.i("Note Uploader", e.getMessage());
}
}
}
Rails replies with the following json object when I issue a post:
{
"notebook":{
"created_android":null,
"created_at":"2011-12-30T06:35:42Z",
"description":"Tatata",
"id":12,
"updated_android":null,
"updated_at":"2011-12-30T06:35:42Z",
"user_id":1
}
}
But this is what I get when I try to print updatedNotebook fields.
12-30 14:35:42.673: INFO/Notebook ID(551): 0
12-30 14:35:42.673: INFO/Notebook userID(551): 0
12-30 14:35:42.673: INFO/Notebook Title(551): null
12-30 14:35:42.673: INFO/Notebook CreatedAt(551): null
12-30 14:35:42.673: INFO/Notebook UpdatedAt(551): null
I'm probably missing something...
Your class doesn't match the JSON.
Your JSON is an object that contains one field ("notebook") which has an object as its value that contains the fields you're actually looking for.
The JSON would need to look like:
{
"created_android":null,
"created_at":"2011-12-30T06:35:42Z",
"description":"Tatata",
"id":12,
"updated_android":null,
"updated_at":"2011-12-30T06:35:42Z",
"user_id":1
}
To map correctly to your object. You also have mismatched field names that need to be corrected. Looks like you got those.
Edit: To clarify, the JSON you have now would currently map to this:
public class NotebookContainer
{
public Notebook notebook;
}
I notice that several of your serialized names do not match the json. android_created and android_updated should have the updated first to match the json. There may be other problems here but that stands out as an issue.
Another approach: If you have control over the Rails dump, you can ignore the root element using ActiveRecord::Base.include_root_in_json = false before your start generating json via to_json
Related
Here's my method where im reading json file.
private void LoadTabaksFromJson() {
InputStream raw = mContext.getResources().openRawResource(R.raw.tabaks);
Reader reader = new BufferedReader(new InputStreamReader(raw));
ListOfTabaks listOfTodos = new Gson().fromJson(reader, ListOfTabaks.class);
List<Tabak> todoList = listOfTodos.getTodoArrayList();
for (Tabak item: todoList){
mDataBase.insert(TabakTable.NAME,null,getContentValues(item));
}
}
public class ListOfTabaks {
protected ArrayList<Tabak> tabakArrayList;
public ArrayList<Tabak> getTodoArrayList(){
return tabakArrayList;
}
}
And Exeption
Caused by: java.lang.NullPointerException: Attempt to invoke interface
method 'java.util.Iterator java.util.List.iterator()' on a null object
reference
at
com.hookah.roma.hookahmix.TabakLab.LoadTabaksFromJson(TabakLab.java:61)
at com.hookah.roma.hookahmix.TabakLab.(TabakLab.java:32)
at com.hookah.roma.hookahmix.TabakLab.get(TabakLab.java:37)
at
com.hookah.roma.hookahmix.TabakListFragment.updateUI(TabakListFragment.java:38)
at
com.hookah.roma.hookahmix.TabakListFragment.onCreateView(TabakListFragment.java:32)
at
android.support.v4.app.Fragment.performCreateView(Fragment.java:2184)
at
android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1298)
at
android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(FragmentManager.java:2323)
at
android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2136)
And json file :
{
"tabaksArrayList":[
{
"name":"Абрикос",
"description":"Со вкусом Абрикоса",
"rating":"4.1",
"favourite":"1",
"family":"Al fakher"
},
{
"name":"Ананас",
"description":"Со вкусом Ананаса",
"rating":"4.1",
"favourite":"1",
"family":"Al fakher"
},
{
"name":"Апельсин",
"description":"Со вкусом Апельсина",
"rating":"4.1",
"favourite":"1",
"family":"Al fakher"
},
{
"name":"Апельсин с мятой",
"description":"Со вкусом Апельсина с мятой",
"rating":"4.1",
"favourite":"1",
"family":"Al fakher"
},
It looks like your json schema issue, i'm guessing listOfTodos return null. You can refer to this to generate your schema.
But sometimes that tools can make us confuse so i tried to create your schema manually like this:
TabakRoot.java
public class TabakRoot {
#SerializedName("tabaksArrayList")
private List<TabakItem> tabakItem = null;
public List<TabakItem> getTabakItem() {
return tabakItem;
}}
TabakItem.java
public class TabakItem {
#SerializedName("family")
#Expose
private String tabakFamily;
public String getTabakFamily() {
return tabakFamily;
}}
finally
TabakRoot listOfTodos = new Gson().fromJson(reader, TabakRoot.class);
List<TabakItem> todoList = listOfTodos.getTabakItem();
Looks like you are not initialising your ArrayList, try changing:
protected ArrayList<Tabak> tabakArrayList;
for:
protected ArrayList<Tabak> tabakArrayList = new ArrayList<>();
Please put your json file in assets folder
use AsyncTask to protect from ANR like situtation
onBackground(){
String json = null;
try {
InputStream stream = activity.getAssets().open("ur_json_file_in_assets_folder.json");
int size = stream.available();
byte[] buffer = new byte[size];
stream.read(buffer);
stream.close();
json = new String(buffer, "UTF-8");
} catch (IOException e) {
e.printStackTrace();
return null;
}
return json;
}
then parse in
onPostExecute(String str){
JsonObject object = new JsonObject(str);
JsonArray arr = object.getJsonArray("tabaksArrayList");
...}
more details at ParseJsonFileAsync.java
You're not initialising tabakArrayList, add a constructor to your ListOfTabaks as following
public ListOfTabaks{
tabakArrayList = new ArrayList<>();
}
and you should be fine
So I already succeed with one Json to get it all worked. Now I have another class where I want to get only one attribute. I have now a moviedatabase class (which work with JSON and gets all the information) and now I want to add a Trailer which is from Youtube API. so basically I need it to be added into the same JSON to make it easier for me in the future to get it into a HTML. the only problem is I cant get it work. I get a syntax error JSON when using this method.
EDIT CODE 1.1:
Youtube attribute:
public class FilmAttribut {
private String title = "";
private String release = "";
private int vote = 0;
private String overview = "";
private String poster = "";
private String trailer = "";
// getters + setters stripped
}
Youtube class:
public class Youtube {
FilmAttribut movie = new FilmAttribut();
public void search(String trailer, FilmAttribut in) {
HttpResponse<JsonNode> response;
try {
response = Unirest.get("https://www.googleapis.com/youtube/v3/search?key=[app key here]&part=snippet")
.queryString("q", trailer + " trailer")
.asJson();
JsonNode json = response.getBody();
JSONObject envelope = json.getObject();
JSONArray items = envelope.getJSONArray("items");
in.setTrailer("https://youtu.be/" + items.getJSONObject(0).getJSONObject("id").getString("videoId")); //Gives me error here
}
catch (JSONException e) {
e.printStackTrace();
} catch (UnirestException e) {
e.printStackTrace();
}
return null;
}
}
and main method
public class WebService {
public static void main(String[] args) {
setPort(1337);
Gson gson = new Gson();
Youtube yt = new Youtube();
MovieDataBase mdb = new MovieDataBase();
get("/search/:movie", (req, res) -> {
String titel = req.params(":movie");
FilmAttribut film = mdb.searchMovie(titel);
yt.search(titel, film);
String json = gson.toJson(film);
return json;
});
So I think the problem is that you can't have two gson.toJson(film) + gson.toJson(trailer); Because it makes the JSON twice, where one time is for the film (aka. movie) and then a new json is created with trailer which make the syntax error.
So my real question is, is it possible to have another class like I have now youtube. to send the information to a attribute class where I have all my attributes and then run it in main-method so that I can get all the JSON in one JSON.
If I did understand well what you are asking, yes you can, but I would do something like that instead:
public void search(String trailer, FileAttribut in) {
// fetch the trailer from youtube (NB: you should use getters/setters, not public fields)
in.setTrailer("https://youtu.be/" + items.getJSONObject(0).getJSONObject("id").getString("videoId"));
}
and:
FilmAttribut film = mdb.searchMovie(titel);
yt.search(titel, film); // pass "film" to "fill" its trailer
return gson.toJson(film);
OR
public String search(String trailer) {
// fetch the trailer from youtube
return "https://youtu.be/" + items.getJSONObject(0).getJSONObject("id").getString("videoId");
}
and:
FilmAttribut film = mdb.searchMovie(titel);
film.setTrailer(yt.search(titel));
return gson.toJson(film);
i'm trying deserialize my object, but I can not get no error!
I'm using gson on android to read json file.
My deserialize
this is my request class, i using a rest server.
public Object getListaSeguradoras(String _codPais, String _tipoPesquisa)
{
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(Config.WS_PATH);
post.setHeader("content-type", "application/json; charset=UTF-8");
post.addHeader("Client-Application","xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
//Make object in JSON format
JSONObject dato = new JSONObject();
dato.put("CodPais", _codPais);
dato.put("TipoPesquisa", _tipoPesquisa);
StringEntity entity = new StringEntity(dato.toString());
post.setEntity(entity);
HttpResponse resp = httpClient.execute(post);
String respStr = EntityUtils.toString(resp.getEntity());
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<SeguradoraLista>>(){}.getType();
Collection<SeguradoraLista> ListaSeguradoras = gson.fromJson(respStr, collectionType);
return ListaSeguradoras;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
My object:
This is my getter and setter
public class SeguradoraLista{
public String SeguradoraId;
public String Nome;
public String getSeguradoraId() {
return this.SeguradoraId;
}
public String getNome() {
return this.Nome;
}
public void setSeguradoraId ( String SeguradoraId) {
this.SeguradoraId = SeguradoraId;
}
public void setNome ( String Nome) {
this.Nome = Nome;
}
}
My json:
this is the json string on my string respStr
[{"SeguradoraId":"19","Nome":"AIG Europe"},
{"SeguradoraId":"25","Nome":"AIOI Insurance Co. Of Europe"},
{"SeguradoraId":"28","Nome":"Aktiv Forsikring A/S"},
{"SeguradoraId":"160","Nome":"Enter Forsikring AS"},
{"SeguradoraId":"167","Nome":"Euro Insurances Ltd."},
{"SeguradoraId":"189","Nome":"Försäkrings-AB Volvia"},
{"SeguradoraId":"219","Nome":"Gjensidige NOR Forsikring"},
{"SeguradoraId":"245","Nome":"If Skadeforsikring NUF"},
{"SeguradoraId":"265","Nome":"Jernbanepersonalets Forsikring Gjensiding"},
{"SeguradoraId":"271","Nome":"KLP Skadeforsikring AS"},
{"SeguradoraId":"284","Nome":"Landbruksforsikring"},
{"SeguradoraId":"309","Nome":"Lloyd's v/Vital Skade AS"},
{"SeguradoraId":"459","Nome":"SpareBank 1 Skadeforsikring AS"},
{"SeguradoraId":"472","Nome":"Tennant Forsikring nuf"},
{"SeguradoraId":"473","Nome":"Terra Skadeforsikring AS"},
{"SeguradoraId":"494","Nome":"Trygg-Hansa Forsikring Nuf"},
{"SeguradoraId":"517","Nome":"Vesta Skadeforsikring A/S"},
{"SeguradoraId":"536","Nome":"Zürich Forsikring"}]
what I'm doing wrong? I can't make this direct deserealizing?
You seem to have an array of SeguradoraLista objects.
So just create a TypeToken of type List<SeguradoraLista>
Type collectionType = new TypeToken<List<SeguradoraLista>>() {}.getType();
List<SeguradoraLista> ListaSeguradoras = gson.fromJson(respStr, collectionType);
Actually, Collection<SeguradoraLista> would work as well.
Suppose I am fetching from an api some json array as so
[{"id":1,"title":"title","description":"description","vote":null,"created_at":"2013-11-12T21:08:10.922Z","updated_at":"2013-11-12T21:08:10.922Z"}]
I want to retrieve this json as an Some object from URL_Some url
public class Some implements Serializable {
private String id;
private String title;
private String description;
private String vote;
private String created_at;
private String updated_at;
}//with all getters and setters
.
public List<Some> getSome() throws IOException {
try {
HttpRequest request = execute(HttpRequest.get(URL_Some));
SomeWrapper response = fromJson(request, SomeWrapper.class);
Field[] fields = response.getClass().getDeclaredFields();
for (int i=0; i<fields.length; i++)
{
try {
Log.i("TAG", (String) fields[i].get(response));
} catch (IllegalAccessException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
Log.i("TAG", fields[i].getName());
}
if (response != null && response.results != null)
return response.results;
return Collections.emptyList();
} catch (HttpRequestException e) {
throw e.getCause();
}
}
and SomeWrapper is simply
private static class SomeWrapper {
private List<Some> results;
}
The problem is that I keep on getting this message
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY
PS : I use
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
Your json should actually be like this:
{"results": [{"id":1,"title":"title","description":"description","vote":null,"created_at":"2013-11-12T21:08:10.922Z","updated_at":"2013-11-12T21:08:10.922Z"}]}
Gson will try to parse the json and create a SomeWrapper object. This alone tells Gson he will wait for a json with this format {...} since he's expecting an object. However you passed an array instead, that's why it complains about expecting BEGIN_OBJECT ({) but getting BEGIN_ARRAY instead ([). After that, it will expect this json object to have a results field, which will hold an array of objects.
You can create List<Some> directly without the need of a wrapper class however. To do so do this instead:
Type type= new TypeToken<List<Some>>() {}.getType();
List<Some> someList = new GsonBuilder().create().fromJson(jsonArray, type);
In this case, you can use the original json array you posted.
The JSON you posted is a JSON array, which is indicated by the squared brackets around it: [ ].
You'd have to read the first object from the JSON array.
I personally use the org.json packages for Android JSON and parse my JSON in a manner like this:
private void parseJSON(String jsonString) {
JSONArray json;
try {
json = new JSONArray(jsonString);
JSONObject jsonObject = jsonArray.getJSONObject(0);
String id = jsonObject.getString("id");
} catch (JSONException jsonex) {
jsonex.printStackTrace();
}
}
If you've got multiple JSON objects in your array you can iterate over them by using a simple for loop (not for each!)
i'm trying to retrieve text from wikipedia to use on an Android app. I'm using Java.
The first thing I want to do is to retrieve the sections from an specific article, show them to the user and, when the user clicks on one section, get the section text with another http request.
So, the two requests are these:
http://en.wikipedia.org/w/api.php?format=json&action=parse&page=Valencia_Cathedral&prop=sections
and then this one:
http://en.wikipedia.org/w/api.php?format=json&action=parse&page=Valencia_Cathedral&prop=text§ion=1
My question is: What kind of java objects should I create to store the information and then convert it to these classes using .fromJSON()?
Thanks to #NathanZ, I created these two classes:
public class WikiResponseSections {
String title;
List<Section> sections;
}
public class Section {
int toclevel;
String level;
String line;
String number;
String index;
String fromtitle;
int byteoffset;
String anchor;
}
But, when I convert the HTTP response to these objets by Gson, and try to read the value of the field 'title' there's an error that triggers: JavaNullPointerException.
Here's my code for the conversion:
InputStream stream = null;
try {
stream = entity.getContent();
} catch (IllegalStateException e) {
Log.e("Stream","ERROR illegalstateexception");
} catch (IOException e) {
Log.e("Stream","ERROR exception");
}
reader = new BufferedReader(new InputStreamReader(stream));
GsonBuilder bldr = new GsonBuilder();
Gson gson = bldr.create();
WikiResponse = gson.fromJson(reader, WikiResponseSections.class);
if (WikiResponse != null){
Log.i("WikiResponse",WikiResponse.getTitle()); //The error triggers HERE
publishProgress();
}
else
Log.i("WikiResponse","NULL");
}
Thanks for your help again
You can use the Google's Gson library.
It works like this:
InputStream source = ...; // your code to get the Json from a url
Gson gson = new Gson();
Reader reader = new InputStreamReader(source);
MyResponse response = gson.fromJson(reader, MyResponse.class);
Where MyResponse is your object. When you create MyResponse, give your fields the same name and type as the Json's fields
MyResponse class can be as follows:
public class MyResponse{
String title;
ArrayList<sections>;
}
public class sections{
int toclevel;
String level;
String line;
String number;
String fromtitle;
long byteoffset;
String anchor;
}
public class WikiResponseParse{
Parse parse;
public class Parse{
String title, text;
}
}
If you can't use the json fields name because it's not Java compliant:
Add the following import:
import com.google.gson.annotations.SerializedName;
and in your class:
#SerializedName("*")
public String star;