40
Views
4
Comments
Issue with Various Meta_Data responses - REST API: Failed to Parse Response
Application Type
Mobile

My client currently uses WooCommerce and I am translating the website to an app for iOS and Android, however my issue comes because they use Meta_Data instead of the WooCommerce built in features for Product attributes etc.


So, the meta_data for each product can vary in terms of what it pulls in as part of it's array. But I can't seem to find a way to try and accommodate for everything. Below is the error I'm getting, my main reason I need to access this data is because the Product Sizes and Colours are part if this Data, but for the life of me I cannot seem to get this API to work for me! The tmfbuilder which you will see below, is the key value I want out of anything that comes back from the API call.


Under the MetaData array, there is:

  • Id - Integer
  • Key - Text
  • Value - (Various possibilities, tmfbuilder being one possibility, a string being another)


I even tried deleting Id and Key from the API response body, and it removed the errors, loaded the prodoct, but it seemed to ignore any data regarding what should have otherwise been behind the tmfbuilder part of the call (sizes and colours of the product).


Here is the error code I get when trying to access a product:

Failed to parse response of the method 'GetProductById2TESTING' of the 'Snickersuk' REST API:Parsing 'meta_data[1].value': Error converting value "2020-05-22" to type 'ssSnickersUK.CcSnickersuk+RESTMeta_datumItem[]'. Path 'meta_data[1].value', line 1, position 7355.Parsing 'meta_data[2].value.tmfbuilder': Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'ssSnickersUK.CcSnickersuk+RESTMeta_datumItem[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.Path 'meta_data[2].value.tmfbuilder', line 1, position 7408.Parsing 'meta_data[3].value': Error converting value "Snickers 6208 LiteWork Detachable Holster Pocket Trousers | SnickersUK" to type 'ssSnickersUK.CcSnickersuk+RESTMeta_datumItem[]'. Path 'meta_data[3].value', line 1, position 18241.


If any help can be provided, I would be most appreciative !


2021-09-06 15-09-53
Dorine Boudry
 
MVP

Hi @Joshua McQuillan ,

it's hard to help without more details, but that specific message you are getting is because your Outsystems software expects an array to come back, but in your test a single object instead of an array comes back.  

Some API's out in the wild sometimes return a single object, and sometimes an array, dependant on the situation, and this is not something Outsystems can deal with out of the box.

One of the options is to fix this in the OnAfterRespons event, see this documentation.

But again, not possible to really help without more detail,

Dorine

UserImage.jpg
Joshua McQuillan

Hi Dorine,

Thank you for your reply. I think I do need to use an OnAfterResponse as you are correct the API returns different values for the same variable in my API, basically polymorphic.

Annoyingly in my current contract, the customers product information is all stored in the Meta_Data, and as this is different per product, it throws up all sorts of errors depending on what product it is trying to load.

Each product does have a unique "meta_data" value, for the actual array that I want, which is the tmfbuilder.. i think i basically need to try and make the reponse only pull this value through, which is my next challanege.

Here is a snippet of the response from the API when a specific product ID has been searched, I've taked out the info before and after, but you can see there are two entries in the reponse before tmfbuilder, and trying to set those values in outsystems isn't possible, as some products have a key which is a string, and some an integer.

I'm wondering if I can use OnAfterResponse to only return any meta_data responses that have a key of "tm_meta", as this seems to persist throughout products. You can see further down the sizes for this product and colours, all nested in this reponse, and this is the key thing I need!

"meta_data": [
    {
      "id": 679225,
      "key": "_children",
      "value": []
    },
    {
      "id": 679232,
      "key": "_wp_old_date",
      "value": "2020-05-22"
    },
    {
      "id": 679251,
      "key": "tm_meta",
      "value": {
        "tmfbuilder": {
          "sections_internal_name": [
            "Section"
          ],
          "section_header_size": [
            "3"
          ],
          "section_header_title": [
            ""
          ],
          "section_header_title_position": [
            ""
          ],
          "section_header_title_color": [
            ""
          ],
          "section_header_subtitle": [
            ""
          ],
          "section_header_subtitle_position": [
            ""
          ],
          "section_header_subtitle_color": [
            ""
          ],
          "section_divider_type": [
            "none"
          ],
          "sections": [
            "4"
          ],
          "sections_slides": [
            ""
          ],
          "sections_size": [
            "w100"
          ],
          "sections_uniqid": [
            "5e440d451a4713.52781068"
          ],
          "sections_style": [
            ""
          ],
          "sections_placement": [
            "before"
          ],
          "sections_type": [
            ""
          ],
          "sections_class": [
            ""
          ],
          "sections_clogic": [
            "{\"toggle\":\"show\",\"what\":\"any\",\"rules\":[]}"
          ],
          "sections_logic": [
            ""
          ],
          "element_type": [
            "selectbox",
            "selectbox",
            "radiobuttons",
            "product"
          ],
          "div_size": [
            "w100",
            "w100",
            "w100",
            "w100"
          ],
          "selectbox_internal_name": [
            "Select Box",
            "Select Box"
          ],
          "selectbox_header_size": [
            "10",
            "10"
          ],
          "selectbox_header_title": [
            "Trouser Size:",
            "Colour:"
          ],
          "selectbox_header_title_position": [
            "",
            ""
          ],
          "selectbox_header_title_color": [
            "",
            ""
          ],
          "selectbox_header_subtitle": [
            "",
            ""
          ],
          "selectbox_header_subtitle_position": [
            "",
            ""
          ],
          "selectbox_header_subtitle_color": [
            "",
            ""
          ],
          "selectbox_divider_type": [
            "none",
            "none"
          ],
          "selectbox_enabled": [
            "1",
            "1"
          ],
          "selectbox_required": [
            "1",
            "1"
          ],
          "selectbox_fee": [
            "",
            ""
          ],
          "selectbox_hide_amount": [
            "",
            ""
          ],
          "selectbox_text_before_price": [
            "",
            ""
          ],
          "selectbox_text_after_price": [
            "",
            ""
          ],
          "selectbox_quantity": [
            "",
            ""
          ],
          "selectbox_quantity_min": [
            "",
            ""
          ],
          "selectbox_quantity_max": [
            "",
            ""
          ],
          "selectbox_quantity_step": [
            "",
            ""
          ],
          "selectbox_quantity_default_value": [
            "",
            ""
          ],
          "selectbox_use_url": [
            "",
            ""
          ],
          "selectbox_changes_product_image": [
            "",
            ""
          ],
          "selectbox_placeholder": [
            "",
            ""
          ],
          "multiple_selectbox_options_default_value": [
            "",
            ""
          ],
          "multiple_selectbox_options_title": [
            [
              "Upto 29W/31L (044)",
              "Upto 30W/31L (046)",
              "Upto 32W/31L (048)",
              "Upto 34W/31L (050)",
              "Upto 35W/31L (052)",
              "Upto 37W/31L (054)",
              "Upto 38W/31L (056)",
              "Upto 40W/31L (058)",
              "Upto 42W/31L (060)",
              "Upto 45W/31L (062)",
              "Upto 29W/29L (088)",
              "Upto 30W/29L (092)",
              "Upto 32W/29L (096)",
              "Upto 34W/29L (100)",
              "Upto 35W/29L (104)",
              "Upto 37W/29L (108)",
              "Upto 38W/29L (112)",
              "Upto 40W/29L (116)",
              "Upto 42W/29L (120)",
              "Upto 30W/34L (146)",
              "Upto 32W/34L (148)",
              "Upto 34W/34L (150)",
              "Upto 35W/34L (152)",
              "Upto 37W/34L (154)",
              "Upto 38W/34L (156)",
              "Upto 40W/34L (158)",
              "Upto 42W/34L (160)",
              "Upto 30W/27L (192)",
              "Upto 32W/27L (196)",
              "Upto 34W/27L (200)",
              "Upto 35W/27L (204)",
              "Upto 37W/27L (208)",
              "Upto 38W/27L (212)",
              "Upto 34W/37L (250)",
              "Upto 35W/37L (252)",
              "Upto 37W/37L (254)",
              "Upto 38W/37L (256)",
              "Upto 40W/37L (258)"
            ],
            [
              "Steel Grey/Black (5804)",
              "Black/Black (0404)",
              "Navy/Black (9504)",
              "Khaki/Black (2004)"
            ]
          ],



2021-09-06 15-09-53
Dorine Boudry
 
MVP

Ok,

so yes, this is going to take some serious trial and error, because if they have a different content for the same label at this highest levels, you may find more of the same at other detail levels of your tmfbuilder object, is my guess.

So, maybe we can assume that there is always at the highest level an id + key + value.  And let's say you are only interested in those values that hold a tmfbuilder object.

you could do something along these lines

1) in your On After Response, you could do a find and replace 

of :  "value": {        "tmfbuilder": {     

by :   "interestingvalue": {        "tmfbuilder": {


2) In your structure in the data tab, representing the output of the api call (this was probably automatically created by OS at the moment you added the api to the consumed api list) you should change the "value" attribute by "interestingvalue" attribute (you don't necessarily have to change the name, but you have to at least change the  Name In JSON property of this attribute.


The result of all of this should be that for the 2 first bits of meta data in your example, you will only have an id and key available in your api result, as the 3rd part will still be named 'value' in the api result after the On After Response, and that doesn't match anything in your receiving structure, 

and for the 3rd piece of metadata, you should get the tmfbuilder object in value (or interestingvalue if you changed the name) as that has been renamed to 'interestingvalue' in the On After Response, and that matches the Name in JSON in your receiving structure.

Dorine

2021-10-09 07-57-44
Stefan Weber
 
MVP

Hi,

for whatever reason i have lots of integrations with dynamic JSON. I created a forge component based on the JSONata Transformation language. (www.jsonata.org). With JSONata you can perform complex transformations to create a deserialize JSON result. https://www.outsystems.com/forge/component-overview/12401/jsonata-transformation

The learning curve however is somewhat steep :-)

Best

Stefan

Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.