0

I have to fight with JSON returns (which i get out of a XML response from Amazon Marketplace API). It contains arrays, subarrays and so on. At the moment i need to get only 2 values (AmazonOrderId and OrderItem object), but i don't find a way to address them directly. I still try for hours. Recursive things scare me a bit.

There are so many tools out there, also for beatifying or editing JSON. So is there possibly also a solution which shows all the property links recursively? Up to now i have not found something like this.

UPDATE: With the code from squint's answer i have build a quick and dirty tool which does what i wanted. Here it is: http://output.jsbin.com/gunixo

like:

myJSON.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].QuantityOrdered
myJSON.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].Title
...

This would really save time, in such a case.

    {
    "ListOrderItemsResponse": {
        "$": {
            "xmlns": "https://mws.amazonservices.com/Orders/2013-09-01"
        },
        "ListOrderItemsResult": [{
            "OrderItems": [{
                "OrderItem": [{
                    "QuantityOrdered": ["1"],
                    "Title": ["My Product Title"],
                    "ShippingTax": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }],
                    "PromotionDiscount": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }],
                    "ConditionId": ["New"],
                    "ASIN": ["BXXXI5W6M8"],
                    "SellerSKU": ["KNDR-BTTWSCH-BGSBNNY"],
                    "OrderItemId": ["67050234000659"],
                    "GiftWrapTax": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }],
                    "QuantityShipped": ["1"],
                    "ShippingPrice": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["4.90"]
                    }],
                    "GiftWrapPrice": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }],
                    "ConditionSubtypeId": ["New"],
                    "ItemPrice": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["15.77"]
                    }],
                    "ItemTax": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }],
                    "ShippingDiscount": [{
                        "CurrencyCode": ["EUR"],
                        "Amount": ["0.00"]
                    }]
                }]
            }],
            "AmazonOrderId": ["304-6107803-0000000"]
        }],
        "ResponseMetadata": [{
            "RequestId": ["dd64dd40-d939-4ea1-875d-xxxxxxxxxxxx"]
        }]
    }
}
Lutz
  • 770
  • 1
  • 8
  • 19
  • If it's an XML response, why are you converting it to JSON? Why not look for a tool to traverse the original XML instead? The data types and structures of XML and JSON really don't map well to each other, so by converting, you're just making it harder to work with the underlying structure. – IMSoP May 17 '15 at 12:26
  • Also, I'm not sure what you're struggling with; the two example lines you give look like they'll work fine with the sample data you've presented. There isn't really any need for recursion, just a lot of deeply nested access into the structure. – IMSoP May 17 '15 at 12:31
  • Thanks for your comment. I use MWS-JS-2014 to connect and retrieve the data from Amazon. This delivers me (only) a JSON object. – Lutz May 17 '15 at 12:32
  • Yes, i'm lucky, these 2 really work. But it is very fiddling to find the correct property link. The examples are 2 of the top ones. It is harder to get the link for lower properties, because I loose the overview. Also because some properties have objects, some have arrays, some have only values... Yesterday i spend hours and have not find the correct links. I have also not found a web service which shows me such property links. but something like this would really help in such a case. – Lutz May 17 '15 at 12:52

1 Answers1

4

If you truly only need those two values, you can do it while it's being parsed.

var data = {};

// ----------v--- Original JSON data before parsing.
JSON.parse(myJSON, function(k, v) {
    if (k === "AmazonOrderId" || k === "OrderItem") {
        data[k] = v;
    }
    return v;
});

That said... recursive stuff shouldn't be scary. And there are many pre-written functions on StackOverflow that accept the property you're looking for and return the value, so you could just use one of those.


Here's a simple recursive function that generates paths to all the data.

function objectToPaths(data) {
  var validId = /^[a-z_$][a-z0-9_$]*$/i;
  var result = [];
  doIt(data, "");
  return result;

  function doIt(data, s) {
    if (data && typeof data === "object") {
      if (Array.isArray(data)) {
        for (var i = 0; i < data.length; i++) {
          doIt(data[i], s + "[" + i + "]");
        }
      } else {
        for (var p in data) {
          if (validId.test(p)) {
            doIt(data[p], s + "." + p);
          } else {
            doIt(data[p], s + "[\"" + p + "\"]");
          }
        }
      }
    } else {
      result.push(s);
    }
  }
}

All Array members are listed individually. This could be consolidated if you know that the data structures in those array members are always identical.

Result for your data:

.ListOrderItemsResponse.$.xmlns
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].QuantityOrdered[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].Title[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingTax[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingTax[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].PromotionDiscount[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].PromotionDiscount[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ConditionId[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ASIN[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].SellerSKU[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].OrderItemId[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].GiftWrapTax[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].GiftWrapTax[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].QuantityShipped[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingPrice[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingPrice[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].GiftWrapPrice[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].GiftWrapPrice[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ConditionSubtypeId[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ItemPrice[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ItemPrice[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ItemTax[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ItemTax[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingDiscount[0].CurrencyCode[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].OrderItems[0].OrderItem[0].ShippingDiscount[0].Amount[0]
.ListOrderItemsResponse.ListOrderItemsResult[0].AmazonOrderId[0]
.ListOrderItemsResponse.ResponseMetadata[0].RequestId[0]
  • Thanks for the answer, but this throws an error for line `JSON.parse(myJSON, function(k, v) {` : SyntaxError: Unexpected token o – Lutz May 17 '15 at 13:59
  • btw: you marked my question as duplicated. the answer you linked may help, but it is not the answer to my question. i know there are many pre-written functions on stackoverflow. i often utilize such functions as a quick solution. i'm sure, sometimes i have not the right keywords to find the solution i look for. anyhow, my question was not for a code snippet. i have asked for a website/webservice which lists the property links or paths for a given JSON. I have searched still more but unfortunately i have not found this. but i found a similar request: github.com/josdejong/jsoneditor/issues/168 – Lutz May 17 '15 at 14:15
  • @Lutz: You're getting an error because you're not passing JSON. See the code comment above. –  May 17 '15 at 14:19
  • You described a problem and the duplicate shows a solution. Just because you presumed a specific solution is better doesn't mean that other answers don't qualify. StackOverflow isn't a 3rd party resource referral service. It's for questions about specific programming problems. If instead of asking about the actual problem, you had attempted to implement such a service and got stuck on something specific, then that would be different. –  May 17 '15 at 14:21
  • but i pass myJASON as first arg to JSON.parse function. isn't the v somethings which will be returned by this function? – Lutz May 17 '15 at 14:31
  • @Lutz: JSON is text data. In a JavaScript program it would be represented as a string type. What you're doing is passing a JavaScript object that was created by parsing JSON data. When you pass a JS object instead of a JSON string, because `.parseJSON` expects a string, it converts it. The default `.toString()` conversion results in `"[object Object]"`. So when the parser gets it, it first sees the `[`, and thinks it should create a JS Array. It then sees the `o`, which would be invalid. –  May 17 '15 at 14:37
  • So pass the *original* JSON instead of the parsed result. –  May 17 '15 at 14:38
  • ok, thanks. so it looks like i need not a solution for JSON, but for "List all property names of an OBJECT incl. subobjects properties"... – Lutz May 17 '15 at 14:42
  • looks like i get an object, not a JSON string from MWS-JS-2014. But i can use JSON.stringify(myJSON) to deliver this. possibly a bit crazy... – Lutz May 17 '15 at 14:46
  • Yes, you could stringify it, but why? The Amazon service is sending you JSON text to begin with, isn't it? –  May 17 '15 at 14:50
  • not efficient, but anyhow it works. thanks – Lutz May 17 '15 at 14:53
  • No, MWS sends XML like on the buttom of this page: http://docs.developer.amazonservices.com/en_DE/orders/2013-09-01/Orders_ListOrderItems.html MWS-JS-2014 which i use to talk to this, delivers me a result object – Lutz May 17 '15 at 14:55
  • Ah, I misunderstood. I thought the JSON was embedded. If you want a more efficient solution, try building a recursive one that does what you want, and if you get stuck, ask and someone will help you complete it. It really shouldn't be all that hard. –  May 17 '15 at 14:59
  • @Lutz: Check it out. http://jsbin.com/hulavalufu/1/ It lists all individual array members too, which could possibly be consolidated if all array members always have the same nested object layout. –  May 17 '15 at 15:17
  • The best and quickest for my case would be what i have searched for. a site which shows property paths for a given JSON. but seems there is nothing like his. :( Anyhow i learned from this question, that i have not JSON in my script. Instead i have an object. And JSON is only something like a "view"to my object. – Lutz May 17 '15 at 15:19
  • YES, this something like this was what i was looking for. Do you have also a like to the script to generate this for me? - for the next case... – Lutz May 17 '15 at 15:23
  • The script I wrote is in the JSBin. That's a live demo. Click the `Edit in JSBin` button on the top-left corner. I also just updated it to use dot instead of bracket notation when possible. http://jsbin.com/ruxazusuge/1/ ...I'll add the function to this answer for simplicity. –  May 17 '15 at 15:26
  • ok, thanks. i had not seen the Edit in JSBin box in right corner, now i have it. – Lutz May 17 '15 at 15:32
  • The script in your new link was not working correct. So i have updated the jsbin with your script from above: http://output.jsbin.com/dahalojudi/1/ – Lutz May 17 '15 at 15:48
  • Weird. I guess JSBin captured it in a partial state. They must save live updates. But yeah, you've got the right one. –  May 17 '15 at 15:54
  • Using your code i have created what i have asked for: http://output.jsbin.com/gunixo Please remove the duplicate marker from my question. I have also updated the question with this solution link. – Lutz May 17 '15 at 20:45