openfoodfacts / openfoodfacts-dart

Open Food Facts API Wrapper
https://pub.dev/packages/openfoodfacts
Apache License 2.0
162 stars 66 forks source link

The new product_name / ingredients_text / categories "in_languages" field break Product.fromJson() #201

Closed stephanegigandet closed 3 years ago

stephanegigandet commented 3 years ago

In Smoothie we save the products as Json and then load them back, but it now fails with version 1.3.0 with the new in languages fields from https://github.com/openfoodfacts/openfoodfacts-dart/pull/185

Discussion in https://github.com/openfoodfacts/smooth-app/pull/442#issuecomment-884819542

I will add a test case in openfoodfacts-dart that exhibits the problem, and @monsieurtanuki said he's working on a solution.

monsieurtanuki commented 3 years ago

I don't think there should be a breaking change: the format of what we get from the server did not change, did it? Or is it rather the fields that we're asking for that are different?

stephanegigandet commented 3 years ago

That's correct, the JSON sent back by the server is exactly the same as before.

But the Dart package's toJson produces a different JSON than what the server returns.

Instead of having product_name_en, product_name_fr etc. they are combined in product_name_in_languages:

{"code":null,"product_name_in_languages":{"en":"Quaker Oats Old Fashioned Oatmeal 18 Ounce Paper Cannister"},"lang":"-","selected_images":{},"images":{},"ingredients_text_in_languages":{"en":"whole grain rolled oats,"},"ingredients_analysis_tags":[],"nutriments":{},"additives_tags":[],"allergens_tags":[],"nutrient_levels":{},"categories_tags_in_languages":{"en":["Plant-based foods and beverages","Plant-based foods","Cereals and potatoes","Cereals and their products"],"fr":["Aliments et boissons à base de végétaux","Aliments d'origine végétale","Céréales et pommes de terre","Céréales et dérivés"]}}

monsieurtanuki commented 3 years ago

@stephanegigandet That's the problem, then. It should be the same json format we get from the server and we send to the server. Am I right?

stephanegigandet commented 3 years ago

@stephanegigandet That's the problem, then. It should be the same json format we get from the server and we send to the server. Am I right?

Right, we currently have a Product.toServerData() function that changes the Product.toJson output to change back the keys to the format used by the server:

  Map<String, String> toServerData() {
    final json = toJson();
[..]

I'm thinking we could do the reverse, we change Product.toJson() to add directly in it the extra processing that is currently in toServerData().

monsieurtanuki commented 3 years ago

@stephanegigandet The thing is that we cannot do exactly what we want because of JsonAnnotation's generated code. But still, we can still edit code in Product.dart:

Map<String, dynamic> toJson() => _$ProductToJson(this);

Careful that it's not exactly the same return type: Map<String, String> toServerData()

stephanegigandet commented 3 years ago

@monsieurtanuki : I made a separate PR to have toJson generate the same JSON as the server, can you take a look at https://github.com/openfoodfacts/openfoodfacts-dart/pull/203 ?

I think it could make sense to merge both:

What do you think?

stephanegigandet commented 3 years ago

Reopening as it works for product_name and ingredients_text, but not tags fields like categories and labels that return a list of strings and not just a string.