Reputation: 3002
I am new to Android and struggling with how to process this data retrieved from an API here. It is a recipe. Below is one example. What I am struggling with is creating a jsonArray of all the items that I can use to show the recipe with it's ingredients and steps in a detail view. I can get the id and name, the single items are fine, specifically the ingredients and steps arrays within the larger recipe array are what I am not quite getting right.
[{"id":2,
"name":"Brownies",
"ingredients":[{"quantity":350,"measure":"G","ingredient":"Bittersweet chocolate (60-70% cacao)"},
{"quantity":226,"measure":"G","ingredient":"unsalted butter"},
{"quantity":300,"measure":"G","ingredient":"granulated sugar"},
{"quantity":100,"measure":"G","ingredient":"light brown sugar"},
{"quantity":5,"measure":"UNIT","ingredient":"large eggs"},
{"quantity":1,"measure":"TBLSP","ingredient":"vanilla extract"},
{"quantity":140,"measure":"G","ingredient":"all purpose flour"},
{"quantity":40,"measure":"G","ingredient":"cocoa powder"},
{"quantity":1.5,"measure":"TSP","ingredient":"salt"},
{"quantity":350,"measure":"G","ingredient":"semisweet chocolate chips"}],
"steps":[{"id":0,"shortDescription":"Recipe Introduction","description":"Recipe Introduction","videoURL":"https:\/\/d17h27t6h515a5.cloudfront.net\/topher\/2017\/April\/58ffdc33_-intro-brownies\/-intro-brownies.mp4","thumbnailURL":""},
{"id":1,"shortDescription":"Starting prep","description":"1. Preheat the oven to 350�F. Butter the bottom and sides of a 9\"x13\" pan.","videoURL":"","thumbnailURL":""},
{"id":2,"shortDescription":"Melt butter and bittersweet chocolate.","description":"2. Melt the butter and bittersweet chocolate together in a microwave or a double boiler. If microwaving, heat for 30 seconds at a time, removing bowl and stirring ingredients in between.","videoURL":"https:\/\/d17h27t6h515a5.cloudfront.net\/topher\/2017\/April\/58ffdc43_1-melt-choclate-chips-and-butter-brownies\/1-melt-choclate-chips-and-butter-brownies.mp4","thumbnailURL":""},
{"id":3,"shortDescription":"Add sugars to wet mixture.","description":"3. Mix both sugars into the melted chocolate in a large mixing bowl until mixture is smooth and uniform.","videoURL":"","thumbnailURL":""},
{"id":4,"shortDescription":"Mix together dry ingredients.","description":"4. Sift together the flour, cocoa, and salt in a small bowl and whisk until mixture is uniform and no clumps remain. ","videoURL":"https:\/\/d17h27t6h515a5.cloudfront.net\/topher\/2017\/April\/58ffdc9e_4-sift-flower-add-coco-powder-salt-brownies\/4-sift-flower-add-coco-powder-salt-brownies.mp4","thumbnailURL":""},{"id":5,"shortDescription":"Add eggs.","description":"5. Crack 3 eggs into the chocolate mixture and carefully fold them in. Crack the other 2 eggs in and carefully fold them in. Fold in the vanilla.","videoURL":"https:\/\/d17h27t6h515a5.cloudfront.net\/topher\/2017\/April\/58ffdc62_2-mix-egss-with-choclate-butter-brownies\/2-mix-egss-with-choclate-butter-brownies.mp4","thumbnailURL":""},{"id":6,"shortDescription":"Add dry mixture to wet mixture.","description":"6. Dump half of flour mixture into chocolate mixture and carefully fold in, just until no streaks remain. Repeat with the rest of the flour mixture. Fold in the chocolate chips.","videoURL":"https:\/\/d17h27t6h515a5.cloudfront.net\/topher\/2017\/April\/58ffdcc8_5-mix-wet-and-cry-batter-together-brownies\/5-mix-wet-and-cry-batter-together-brownies.mp4","thumbnailURL":""},{"id":7,"shortDescription":"Add batter to pan.","description":"7. Pour the batter into the prepared pan and bake for 30 minutes.","videoURL":"https:\/\/d17h27t6h515a5.cloudfront.net\/topher\/2017\/April\/58ffdcf4_8-put-brownies-in-oven-to-bake-brownies\/8-put-brownies-in-oven-to-bake-brownies.mp4","thumbnailURL":""},{"id":8,"shortDescription":"Remove pan from oven.","description":"8. Remove the pan from the oven and let cool until room temperature. If you want to speed this up, you can feel free to put the pan in a freezer for a bit.","videoURL":"","thumbnailURL":""},{"id":9,"shortDescription":"Cut and serve.","description":"9. Cut and serve.","videoURL":"https:\/\/d17h27t6h515a5.cloudfront.net\/topher\/2017\/April\/58ffdcf9_9-final-product-brownies\/9-final-product-brownies.mp4","thumbnailURL":""}],
"servings":8,
"image":""}]
What I have been trying to use to process that data is this.
public static String[] getSimpleRecipeStringsFromJson(Context context, String recipeJsonStr)
throws JSONException {
String[] parsedRecipeData = null;
JSONArray recipeJSONArray = new JSONArray(recipeJsonStr);
parsedRecipeData = new String[recipeJSONArray.length()];
// Loop through the recipe array
for (int i = 0; i < recipeJSONArray.length(); i++) {
JSONObject recipeDetails = recipeJSONArray.getJSONObject(i);
String recipeID = recipeDetails.getString("id");
String recipeName = recipeDetails.getString("name");
String recipeIngredients = recipeDetails.getString("ingredients");
String servings = recipeDetails.getString("servings");
String image = recipeDetails.getString("image");
String[] parsedRecipeIngredientsData = null;
JSONArray recipeIngredientsJSONArray = new JSONArray(recipeIngredients);
parsedRecipeIngredientsData = new String[recipeIngredientsJSONArray.length()];
// Loop through ingredients array
for (int ingredient = 0; ingredient < recipeIngredientsJSONArray.length(); ingredient++) {
JSONObject ingredientDetails = recipeIngredientsJSONArray.getJSONObject(ingredient);
String ingredientQuantity = ingredientDetails.getString("quantity");
String ingredientMeasure = ingredientDetails.getString("measure");
String ingredientIngredient = ingredientDetails.getString("ingredient");
parsedRecipeIngredientsData[ingredient] = "\"" + ingredientQuantity + "\",\"" + ingredientMeasure + "\",\"" + ingredientIngredient + "\"";
Log.d(TAG, "CHECK : " + parsedRecipeIngredientsData[ingredient]);
}
parsedRecipeData[i] = "[\"" + recipeID + "\",\"" + recipeName + "\",\"" + parsedRecipeIngredientsData + "]\",\"" + servings + "\",\"" + image + "\"]";
Log.d(TAG, "TAG : " + parsedRecipeData[i]);
}
return parsedRecipeData;
}
I am using it in the detail view like this, right now it just shows the recipe name, this is where I need all the information.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recipe_detail);
// Creating variables for each of the items we need to display
mRecipeName = (TextView) findViewById(R.id.recipe_name);
mRecipeIngredients = (TextView) findViewById(R.id.recipe_ingredients);
Intent intentThatStartedThisActivity = getIntent();
if (intentThatStartedThisActivity != null) {
if (intentThatStartedThisActivity.hasExtra(Intent.EXTRA_TEXT)) {
Context context = getApplicationContext();
mRecipe = intentThatStartedThisActivity.getStringExtra(Intent.EXTRA_TEXT);
try {
JSONArray jsonArray = new JSONArray(mRecipe);
String recipeID = jsonArray.getString(0);
// Display title
mRecipeName.setText(jsonArray.getString(1));
} catch (JSONException e) {
Log.d(TAG, "CHECK : " + e);
e.printStackTrace();
}
}
}
}
I was hoping I could create ingredients and steps arrays that I could later loop through but I keep getting errors. The object produced by this code looks like this.
["4","Cheesecake","[Ljava.lang.String;@e5c064e}","8",""]
So that java.lang.string is is the issue. I though creating a String[] would allow me to loop through it later as that is the data sent to this method and I was just trying to duplicate that but I cannot get it to work out. I get the error
unterminated array character at ### (the numbers change)
So maybe I am just formatting it incorrectly, or I need a different approach. If someone could give me a hint as to how to process something like the recipe above into a useable jsonArray that I can use to populate a view, it would be greatly appreciated. Even just a link to an example or method to look into would be much appreciated.
Upvotes: 1
Views: 370
Reputation: 1354
I know it doesn't answer the answer directly, but when it comes to serialize and deserialize Json in android i suggest using GSON, a useful library by google
By using it you can create 3 classes like below
public class Recipe {
@SerializedName("id")
public Integer id;
@SerializedName("name")
public String name;
@SerializedName("ingredients")
public List<Ingredient> ingredients = null;
@SerializedName("steps")
public List<Step> steps = null;
@SerializedName("servings")
public Integer servings;
@SerializedName("image")
public String image;
}
public class Ingredient {
@SerializedName("quantity")
public Double quantity;
@SerializedName("measure")
public String measure;
@SerializedName("ingredient")
public String ingredient;
}
public class Step {
@SerializedName("id")
public Integer id;
@SerializedName("shortDescription")
public String shortDescription;
@SerializedName("description")
public String description;
@SerializedName("videoURL")
public String videoURL;
@SerializedName("thumbnailURL")
public String thumbnailURL;
}
And then parse your JSON like this
private List<Recipe> mRecipes;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recipe_detail);
// Creating variables for each of the items we need to display
mRecipeName = (TextView) findViewById(R.id.recipe_name);
mRecipeIngredients = (TextView) findViewById(R.id.recipe_ingredients);
Intent intentThatStartedThisActivity = getIntent();
if (intentThatStartedThisActivity != null) {
if (intentThatStartedThisActivity.hasExtra(Intent.EXTRA_TEXT)) {
Context context = getApplicationContext();
mRecipes = new Gson().fromJson(intentThatStartedThisActivity.getStringExtra(Intent.EXTRA_TEXT), new TypeToken<List<Recipe>>(){}.getType());
}
}
}
Upvotes: 1
Reputation: 3103
As you want to use Normal JSON parsing, you can use below code to parse every tag of your posted JSON.
try {
JSONObject mainObj = new JSONObject("Your API Response");
String id = mainObj.getString("id");
String name = mainObj.getString("name");
String servings = mainObj.getString("servings");
String image = mainObj.getString("image");
JSONArray ingredients = mainObj.getJSONArray("ingredients");
for(int i=0;i<ingredients.length();i++){
JSONObject jobj = ingredients.getJSONObject(i);
String quantity = jobj.getString("quantity");
String measure = jobj.getString("measure");
String ingredient = jobj.getString("ingredient");
String chocolate = jobj.getString("chocolate");
}
JSONArray steps = mainObj.getJSONArray("steps");
for(int i=0;i<ingredients.length();i++){
JSONObject jobj = ingredients.getJSONObject(i);
String ids = jobj.getString("id");
String shortDescription = jobj.getString("shortDescription");
String description = jobj.getString("description");
String videoURL = jobj.getString("videoURL");
String thumbnailURL = jobj.getString("thumbnailURL");
}
} catch (Exception e) {
e.printStackTrace();
}
Upvotes: 0
Reputation: 1266
What you need is a librarby like GSON or Jakson These libraries will turn JSON into a pojo. In order to do this, you will have to declare a java class that defines your JSON response model.
If you use android studio(why wouldn't you be!), I recommend installing a plugin named DTO Generator, this plugin will generate the java classes for you, so you don't even have to type up all the classes and properties.
The links have all the tutorial you will need. However, most networking level libraries such as RETROFIT/OKHTTP will let you declare your JSON parser, so they will directly use the JSON library in every network call and turn the responses into POJO.
I don't know which network library you use, but I just google "how to use gson with retrofit" etc and there are plenty of tutorials out there that can help you.
Upvotes: 0
Reputation: 5589
To read the arrays you have to pick them up like this:
JSONArray recipeIngredients = recipeDetails.getJSONArray("ingredients");
JSONArray steps = recipeDetails.getJSONArray("steps");
not as Strings.
Doing it this way you you can loop through the JSONArray
and extract each JSONObject
form it. And form the JSONObject
, the Strings you need.
Upvotes: 0
Reputation: 11491
You can use gson to parse JSON data more easily. In your build.gradle file add this dependency.
compile 'com.google.code.gson:gson:2.8.0'
Parse data like this
Gson gson = new Gson();
Data data= gson.fromJson(json,Data.class);
Here is the Data class
public class Data {
@SerializedName("id")
@Expose
public int id;
@SerializedName("name")
@Expose
public String name;
@SerializedName("ingredients")
@Expose
public List<Ingredient> ingredients = null;
@SerializedName("steps")
@Expose
public List<Step> steps = null;
@SerializedName("servings")
@Expose
public int servings;
@SerializedName("image")
@Expose
public String image;
}
Here is the Ingredient class
public class Ingredient {
@SerializedName("quantity")
@Expose
public int quantity;
@SerializedName("measure")
@Expose
public String measure;
@SerializedName("ingredient")
@Expose
public String ingredient;
}
Here is the Step class
public class Step {
@SerializedName("id")
@Expose
public int id;
@SerializedName("shortDescription")
@Expose
public String shortDescription;
@SerializedName("description")
@Expose
public String description;
@SerializedName("videoURL")
@Expose
public String videoURL;
@SerializedName("thumbnailURL")
@Expose
public String thumbnailURL;
}
Upvotes: 1