【问题标题】:Android Room Write Custom Nested ObjectsAndroid Room 编写自定义嵌套对象
【发布时间】:2020-11-21 07:12:11
【问题描述】:

好的,我已经使用 Retrofit 库成功地将 GET 请求发送到服务器,并在我的应用程序中解析了该数据。现在我想将该数据(我创建的自定义模型类)存储在 ROOM 数据库中,但是我有很多模型类。那么在数据库中编写自定义对象的最佳方法是什么,我应该如何为此编写类型转换器?检查我的网络响应以了解数据的复杂程度:

{
  "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"
    }
  ]
}

【问题讨论】:

  • 你想把整本烹饪书存入数据库吗?:D
  • @a_local_nobody 没问题,在 Google 上搜索 spoonacular
  • @EugeneTroyanskii 我想存储从 API 获得的食谱列表,并将它们存储在数据库中,这样我就不必每次都请求它们。每次我得到新列表时,只需用 Replace onConflictStrategy 替换旧列表。
  • 这样的转换器会很慢,因为要进行大量的转换。您必须为每个数组和每个自定义类型添加转换器。这看起来不是明智的想法。无论如何,如果你想尝试的话,你可以使用通用转换器到/从字符串;)
  • 我建议专门围绕您想要显示/保存的数据创建模型,而不仅仅是保存所有这些

标签: android json kotlin android-room


【解决方案1】:

虽然没有最好的方法来处理这个问题,除了必须为每个字段创建转换器模型之外,明智的将您要保存的数据量限制为仅相关信息您将需要,然后使用自定义转换器自动转换您的数据。

根据 OP 在 cmets 中的要求,这是一个基本示例,说明如何为列表/数组添加类型转换器(使用 Gson):

扩展方法:

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

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

转换器:

 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

【讨论】:

  • 谢谢我的朋友! :)
  • 嘿,我尝试使用您提供的代码,但我有几个问题。所以基本上我需要将arrayList转换为gson(写入时)并从gson转换回数组列表(读取db时)?我很困惑,我实际上不明白这段代码应该做什么..
  • @StefanJo 你自己不会真正使用这个代码,你会把它交给你的房间数据库使用,它会自动进行这些转换,看看this link
  • 不,谢谢@StefanJo :) 我为社区而帮助,因为它很有趣,如果您有任何具体的需求,请随时提出新问题,然后每个人都可以提供帮助,我会的一定要看看,我不是什么都知道,有的用户要好得多
猜你喜欢
  • 1970-01-01
  • 2018-02-03
  • 2011-01-13
  • 1970-01-01
  • 2011-04-17
  • 2012-12-02
  • 1970-01-01
  • 2020-04-21
  • 2019-09-29
相关资源
最近更新 更多