0

Okay so I've successfully sent GET request to a server using Retrofit library, and parsed that data in my app. Now I want to store that data(custom model classes which I have created) in ROOM database, however I have a lot of model classes. So what's the best way to write that custom objects in database, how should I write type converters for this? Check my network response to understand how complex the data is:

{
  "recipes": [
    {
      "vegetarian": false,
      "vegan": false,
      "glutenFree": true,
      "dairyFree": false,
      "veryHealthy": false,
      "cheap": false,
      "veryPopular": false,
      "sustainable": false,
      "weightWatcherSmartPoints": 9,
      "gaps": "no",
      "lowFodmap": false,
      "aggregateLikes": 27,
      "spoonacularScore": 27,
      "healthScore": 2,
      "creditsText": "Foodista.com – The Cooking Encyclopedia Everyone Can Edit",
      "license": "CC BY 3.0",
      "sourceName": "Foodista",
      "pricePerServing": 168.58,
      "extendedIngredients": [
        {
          "id": 1001,
          "aisle": "Milk, Eggs, Other Dairy",
          "image": "butter-sliced.jpg",
          "consistency": "solid",
          "name": "butter",
          "original": "1 tablespoon butter",
          "originalString": "1 tablespoon butter",
          "originalName": "butter",
          "amount": 1,
          "unit": "tablespoon",
          "meta": [],
          "metaInformation": [],
          "measures": {
            "us": {
              "amount": 1,
              "unitShort": "Tbsp",
              "unitLong": "Tbsp"
            },
            "metric": {
              "amount": 1,
              "unitShort": "Tbsp",
              "unitLong": "Tbsp"
            }
          }
        },
        {
          "id": 10011268,
          "aisle": "Produce;Ethnic Foods",
          "image": "dried-porcini-mushrooms.png",
          "consistency": "solid",
          "name": "dried porcini mushrooms",
          "original": "1 cup porcini mushrooms (dried or fresh)",
          "originalString": "1 cup porcini mushrooms (dried or fresh)",
          "originalName": "porcini mushrooms (dried or fresh)",
          "amount": 1,
          "unit": "cup",
          "meta": [
            "fresh",
            "()"
          ],
          "metaInformation": [
            "fresh",
            "()"
          ],
          "measures": {
            "us": {
              "amount": 1,
              "unitShort": "cup",
              "unitLong": "cup"
            },
            "metric": {
              "amount": 236.588,
              "unitShort": "ml",
              "unitLong": "milliliters"
            }
          }
        },
        {
          "id": 1053,
          "aisle": "Milk, Eggs, Other Dairy",
          "image": "fluid-cream.jpg",
          "consistency": "liquid",
          "name": "heavy cream",
          "original": "1/2 cup heavy cream (or until desired consistency)",
          "originalString": "1/2 cup heavy cream (or until desired consistency)",
          "originalName": "heavy cream (or until desired consistency)",
          "amount": 0.5,
          "unit": "cup",
          "meta": [
            "(or until desired consistency)"
          ],
          "metaInformation": [
            "(or until desired consistency)"
          ],
          "measures": {
            "us": {
              "amount": 0.5,
              "unitShort": "cups",
              "unitLong": "cups"
            },
            "metric": {
              "amount": 118.294,
              "unitShort": "ml",
              "unitLong": "milliliters"
            }
          }
        },
        {
          "id": 1033,
          "aisle": "Cheese",
          "image": "parmesan.jpg",
          "consistency": "solid",
          "name": "parmesan cheese",
          "original": "1 cup grated Parmesan cheese (or more to taste)",
          "originalString": "1 cup grated Parmesan cheese (or more to taste)",
          "originalName": "grated Parmesan cheese (or more to taste)",
          "amount": 1,
          "unit": "cup",
          "meta": [
            "grated",
            "to taste",
            "( )"
          ],
          "metaInformation": [
            "grated",
            "to taste",
            "( )"
          ],
          "measures": {
            "us": {
              "amount": 1,
              "unitShort": "cup",
              "unitLong": "cup"
            },
            "metric": {
              "amount": 236.588,
              "unitShort": "ml",
              "unitLong": "milliliters"
            }
          }
        },
        {
          "id": 10035137,
          "aisle": "Pasta and Rice;Ethnic Foods;Baking",
          "image": "cornmeal.png",
          "consistency": "solid",
          "name": "polenta",
          "original": "1 cup polenta",
          "originalString": "1 cup polenta",
          "originalName": "polenta",
          "amount": 1,
          "unit": "cup",
          "meta": [],
          "metaInformation": [],
          "measures": {
            "us": {
              "amount": 1,
              "unitShort": "cup",
              "unitLong": "cup"
            },
            "metric": {
              "amount": 236.588,
              "unitShort": "ml",
              "unitLong": "milliliters"
            }
          }
        },
        {
          "id": 2047,
          "aisle": "Spices and Seasonings",
          "image": "salt.jpg",
          "consistency": "solid",
          "name": "salt",
          "original": "Salt to taste",
          "originalString": "Salt to taste",
          "originalName": "Salt to taste",
          "amount": 6,
          "unit": "servings",
          "meta": [
            "to taste"
          ],
          "metaInformation": [
            "to taste"
          ],
          "measures": {
            "us": {
              "amount": 6,
              "unitShort": "servings",
              "unitLong": "servings"
            },
            "metric": {
              "amount": 6,
              "unitShort": "servings",
              "unitLong": "servings"
            }
          }
        },
        {
          "id": 14412,
          "aisle": "Beverages",
          "image": "water.png",
          "consistency": "liquid",
          "name": "water",
          "original": "4 cups water",
          "originalString": "4 cups water",
          "originalName": "water",
          "amount": 4,
          "unit": "cups",
          "meta": [],
          "metaInformation": [],
          "measures": {
            "us": {
              "amount": 4,
              "unitShort": "cups",
              "unitLong": "cups"
            },
            "metric": {
              "amount": 946.352,
              "unitShort": "ml",
              "unitLong": "milliliters"
            }
          }
        }
      ],
      "id": 640677,
      "title": "Creamy Porcini Mushroom Polenta",
      "readyInMinutes": 45,
      "servings": 6,
      "sourceUrl": "http://www.foodista.com/recipe/F38KZJ88/creamy-porcini-mushroom-polenta",
      "image": "https://spoonacular.com/recipeImages/640677-556x370.jpg",
      "imageType": "jpg",
      "summary": "Creamy Porcini Mushroom Polentan is a <b>gluten free</b> side dish. This recipe makes 6 servings with <b>263 calories</b>, <b>9g of protein</b>, and <b>14g of fat</b> each. For <b>$1.69 per serving</b>, this recipe <b>covers 7%</b> of your daily requirements of vitamins and minerals. Head to the store and pick up water, porcini mushrooms, heavy cream, and a few other things to make it today. 27 people have made this recipe and would make it again. From preparation to the plate, this recipe takes approximately <b>45 minutes</b>. All things considered, we decided this recipe <b>deserves a spoonacular score of 30%</b>. This score is not so super. Try <a href=\"https://spoonacular.com/recipes/wild-mushroom-polenta-with-porcini-sauce-620778\">Wild Mushroom Polenta with Porcini Sauce</a>, <a href=\"https://spoonacular.com/recipes/creamy-polenta-mushroom-ragout-502641\">Creamy polenta & mushroom ragout</a>, and <a href=\"https://spoonacular.com/recipes/polenta-with-creamy-mushroom-sauce-695425\">Polenta with Creamy Mushroom Sauce</a> for similar recipes.",
      "cuisines": [],
      "dishTypes": [
        "side dish"
      ],
      "diets": [
        "gluten free"
      ],
      "occasions": [],
      "winePairing": {},
      "instructions": "<ol><li>In a large heavy bottomed saucepan, season water with salt and bring to a boil. Quickly whisk in the polenta until fully incorporated.</li><li>Lower the heat to a simmer, add the butter and porcini and allow the polenta to cook, stirring occasionally for about 30 minutes.</li><li>Finish by stirring in the cream and Parmesan cheese. If necessary, add salt to taste.</li></ol>",
      "analyzedInstructions": [
        {
          "name": "",
          "steps": [
            {
              "number": 1,
              "step": "In a large heavy bottomed saucepan, season water with salt and bring to a boil. Quickly whisk in the polenta until fully incorporated.Lower the heat to a simmer, add the butter and porcini and allow the polenta to cook, stirring occasionally for about 30 minutes.Finish by stirring in the cream and Parmesan cheese. If necessary, add salt to taste.",
              "ingredients": [
                {
                  "id": 1033,
                  "name": "parmesan",
                  "localizedName": "parmesan",
                  "image": "parmesan.jpg"
                },
                {
                  "id": 10035137,
                  "name": "polenta",
                  "localizedName": "polenta",
                  "image": "cornmeal.png"
                },
                {
                  "id": 1001,
                  "name": "butter",
                  "localizedName": "butter",
                  "image": "butter-sliced.jpg"
                },
                {
                  "id": 1053,
                  "name": "cream",
                  "localizedName": "cream",
                  "image": "fluid-cream.jpg"
                },
                {
                  "id": 14412,
                  "name": "water",
                  "localizedName": "water",
                  "image": "water.png"
                },
                {
                  "id": 2047,
                  "name": "salt",
                  "localizedName": "salt",
                  "image": "salt.jpg"
                }
              ],
              "equipment": [
                {
                  "id": 404669,
                  "name": "sauce pan",
                  "localizedName": "sauce pan",
                  "image": "sauce-pan.jpg"
                },
                {
                  "id": 404661,
                  "name": "whisk",
                  "localizedName": "whisk",
                  "image": "whisk.png"
                }
              ],
              "length": {
                "number": 30,
                "unit": "minutes"
              }
            }
          ]
        }
      ],
      "originalId": null,
      "spoonacularSourceUrl": "https://spoonacular.com/creamy-porcini-mushroom-polenta-640677"
    }
  ]
}
StefanJo
  • 275
  • 3
  • 13
  • Do you wanna store whole cooking book in DB?:D – Eugene Troyanskii Jul 31 '20 at 12:46
  • @a_local_nobody Sure no problem, search spoonacular on Google – StefanJo Jul 31 '20 at 12:46
  • @EugeneTroyanskii I want to store a list of recipes which I get from API, and store them in DB so I dont have to request them everytime. And everytime I get new list, just replace the old one with Replace onConflictStrategy. – StefanJo Jul 31 '20 at 12:48
  • 2
    such converters gonna be very slow because a tons of conversion. You have to add converter for each Array and each custom type. It looks like not wise idea. Anyway if you wish you can use common converter to/from string if you wish to try;) – Eugene Troyanskii Jul 31 '20 at 12:51
  • thank you :) also, i do agree with what @EugeneTroyanskii is saying, i can't think of a simpler or easier way of storing this data, you'll need to create quite a few [type converters](https://developer.android.com/training/data-storage/room/referencing-data) to handle this data – a_local_nobody Jul 31 '20 at 12:52
  • @EugeneTroyanskii Okay so the best solution would be reducing the amount of data that I want to show in my app? I have only used typical converters from/to String, but haven't used ones with arrays, lists etc...can you share me a link where I can find some examples for that? – StefanJo Jul 31 '20 at 12:53
  • 1
    i'd suggest creating models based specifically around the data that you'd want to display/save and not just saving all of this – a_local_nobody Jul 31 '20 at 12:54

1 Answers1

1

Although there's no best way of handling this, besides having to create converters models for each of these fields, it would be wise to limit the amount of data you're saving to only the relevant information that you're going to need and then to use custom converters to convert your data automatically.

As requested by OP in the comments, here's a basic example of how you can add a type converter for a list/array (making use of Gson):

extension methods:

 fun <T> String.fromGson(classOfT: Class<T>) = Gson().fromJson(this, classOfT)

 fun Any.toGson() = Gson().toJson(this)

converter:

 class MyConverter {
    @TypeConverter
    fun toListOfObjects(value: String?): List<Foo> {
        if (value.isNullOrEmpty()) {
            return emptyList()
        }

        val jsonArray = value.fromGson(JsonArray::class.java)

        return jsonArray.map { jsonArray -> jsonArray.fromGson(Foo::class.java) }
    }

    @TypeConverter
    fun toString(value: List<Foo>?) = value?.toGson()
}

similar question/answer

a_local_nobody
  • 7,947
  • 5
  • 29
  • 51
  • Thank you my friend! :) – StefanJo Jul 31 '20 at 13:05
  • Hey I tried to use that code you have provided and I have few questions. So basically I need to convert arrayList to gson (when writing) and from gson back to array list (when reading db)? I'm confused, I actually don't understand what should this code do.. – StefanJo Jul 31 '20 at 16:06
  • @StefanJo you won't actually use this code yourself, you'll give it to your room database to use and it will do these conversion automatically, have a look at [this link](https://developer.android.com/training/data-storage/room/referencing-data) – a_local_nobody Jul 31 '20 at 16:25
  • 1
    no thanks @StefanJo :) i help for the sake of the community and because it's fun, if there's anything specific you want, feel free to ask a new question, then everyone can help, i'll be sure to look at it as well, i don't know everything, there are users who are far better – a_local_nobody Jul 31 '20 at 16:33