eBay Finding API. Why are findItemsAdvanced JSON result items as arrays?

When calling findItemsAdvanced with, the RESPONSE-DATA-FORMAT=XML

results are expected, for example:

<findItemsAdvancedResponse xmlns="http://www.ebay.com/marketplace/search/v1/services">
  <ack>Success</ack>
  <version>1.13.0</version>
  <timestamp>2014-11-16T20:59:57.588Z</timestamp>
  <searchResult count="0"/>
  <paginationOutput>
    <pageNumber>0</pageNumber>
    <entriesPerPage>100</entriesPerPage>
    <totalPages>0</totalPages>
    <totalEntries>0</totalEntries>
  </paginationOutput>
  <itemSearchURL>http://www.ebay.co.uk/sch/i.html?_nkw=mytest1</itemSearchURL>
</findItemsAdvancedResponse>

      

But calling the same thing with RESPONSE-DATA-FORMAT=JSON

, the individual elements are all wrapped in []

:

{"findItemsAdvancedResponse":[
  {"ack":["Success"],
   "version":["1.13.0"],
   "timestamp":["2014-11-16T20:58:14.639Z"],
   "searchResult":[
    {"@count":"0"}],
   "paginationOutput":[
     {"pageNumber":["0"],
      "entriesPerPage":["100"],
      "totalPages":["0"],
      "totalEntries":["0"]}],
   "itemSearchURL":["http:\/\/www.ebay.co.uk\/sch\/i.html?&_nkw=mytest1"]
  }]
}

      

It seems like it hurts to extract the results using Javascript, for example:

response.findItemsAdvancedResponse[0].paginationOutput[0].pageNumber[0]

      

Am I missing something or is something wrong? (Unless you consider querying the results in XML and using the XML => JSON Transform Tool ...)

+3


source to share


5 answers


No one seems to be worried about it?

I am using AngularJS and I want to have the Ebay API as a backend. I have to write a $ resource interceptor to collapse all arrays that only have one child to remove the fallback [] brackets.

A generic interceptor can solve this elegance, but I think this is a bug.

I asked a question about the Ebay developer form here: https://forums.developer.ebay.com/questions/16385/why-does-search-return-json-items-as-array.html#answer-16386



I am linking to this page on the ebay forum - hope it helps others.

Edit:

... and for completeness, here is the code I used . It may not be very pretty, but it worked for me. YMMV

var resp = {"findItemsAdvancedResponse":[
   {"ack":["Success"],
    "version":["1.13.0"],
    "timestamp":["2014-11-16T20:58:14.639Z"],
    "searchResult":[
     {"@count":"0"}],
    "paginationOutput":[
      {"pageNumber":["0"],
       "entriesPerPage":["100"],
       "totalPages":["0"],
       "totalEntries":["0"]}],
    "itemSearchURL":["http:\/\/www.ebay.co.uk\/sch\/i.html?&_nkw=mytest1"]
   }]
 };

var flatten = function( obj ) {
    var ret = {};

  if( String === obj.constructor || Number === obj.constructor ) {
    return obj;
  }

  for(var prop in obj) {
    if(!obj.hasOwnProperty(prop)) continue;

    if( String === obj[prop].constructor || Number === obj[prop].constructor ) {
        ret[prop] = obj[prop];
      continue;
    }

    if( Object.prototype.toString.call( obj[prop] ) === '[object Array]' ) {
      if( obj[prop].length==0 )
        ret[prop] = null;
      if( obj[prop].length==1 && "0" in obj[prop] ) {
        ret[prop] = flatten(obj[prop][0]);
      } else {
        ret[prop] = flatten(obj[prop]);
      }
      continue; // skip below: all arrays are Objects...!
    }

    if( Object === obj[prop].constructor ) {
      ret[prop] = flatten( obj[prop] );
      continue;
    }

  }
  return ret;
};

console.log( resp );
resp = flatten( resp );
console.log( resp );
console.log( resp.findItemsAdvancedResponse.ack );

      

+2


source


This is very similar to DerekC's parsing function pretty fast. It focuses on finding elements that are arrays with Array.isArray()

and of length 1 with values ​​that are not objects. Nothing fancy, super clean and super fast.

The function is named ebayFormat

, just below the same response object used by DerekC .



var resp = {"findItemsAdvancedResponse":[
   {"ack":["Success"],
    "version":["1.13.0"],
    "timestamp":["2014-11-16T20:58:14.639Z"],
    "searchResult":[
     {"@count":"0"}],
    "paginationOutput":[
      {"pageNumber":["0"],
       "entriesPerPage":["100"],
       "totalPages":["0"],
       "totalEntries":["0"]}],
    "itemSearchURL":["http:\/\/www.ebay.co.uk\/sch\/i.html?&_nkw=mytest1"]
   }]
 };

  function ebayFormat(item) {
    if (typeof item === 'object') {
      if (Array.isArray(item) && item.length === 1 && typeof item[0] !== 'object') item = item[0];
      else {
        var keys = Object.keys(item),
          i = 0,
          len = keys.length;
        for (; i < len; i++) {
          if (typeof item[keys[i]] === 'object') item[keys[i]] = ebayFormat(item[keys[i]]);
        }
      }
    }
    return item;
  }

console.log( resp );
resp = ebayFormat( resp );
console.log( resp );
console.log( resp.findItemsAdvancedResponse.ack );

      

+1


source


I have the same problem, I have solved a recursive function to solve it (remove the array when array length = 1 and not excluded)

objJsonFromEbay = findAndCorrect(objJsonFromEbay);

    function findAndCorrect(obj){

        let o = obj,
            exclu = ['item'];

        for (const key in o) {
            if (o.hasOwnProperty(key)) {
                const val = o[key];

                if(Array.isArray(val) && val.length == 1){
                    if(exclu.indexOf(key) == -1)
                        o[key] = val[0];
                    o[key] = findAndCorrect(o[key]);
                }else if(!Array.isArray(val) && typeof val == 'object'){                        
                    o[key] = findAndCorrect(val);
                }
            }
        }
        return o;
    }

      

exclu is an array for each item that you expect to be stored in Array format. Might be useful if you ever use it to get products or other data that you expect in an array

+1


source


I had the same problem and was curious if I still had problems if I decided to use an XML response instead of a JSON response and use an XML-to-JSON converter for the returned data - and lo and behold, still exactly like this same problem.

The converter I would end up using is called xml2js , which seems to be extremely popular on NPM (north of 3.5M monthly downloads according to NPM at the time of this answer).

xml2js has an option called explicitArray

within its parseString

behavior that behaves as they document:

Always put child nodes in an array if true; otherwise, the array is only created if there is more than one.

This behavior seems to mimic some of the answers listed here, but since it is part of a widely used community solution, I feel more comfortable with the solution compared to the home solution.

In practice, it looks as simple as:

import { parseString as xml2js } from 'xml2js';

...

xml2js(someXmlString, { explicitArray: false }, (err, results) => {
  // do something with 'results'
});

      

https://www.npmjs.com/package/xml2js

+1


source


This is JSON. What did you expect from JSON? :-)

{"findItemsAdvancedResponse":[
  {"ack":["Success"],
   "version":["1.13.0"],
   "timestamp":["2014-11-16T20:58:14.639Z"],
   "searchResult":[
    {"@count":"0"}],
   "paginationOutput":[
     {"pageNumber":["0"],
      "entriesPerPage":["100"],
      "totalPages":["0"],
      "totalEntries":["0"]}],
   "itemSearchURL":["http:\/\/www.ebay.co.uk\/sch\/i.html?&_nkw=mytest1"]
  }]
}

      

Try going to http://jsonviewer.stack.hu/ and pasting the JSON string in the Text section and clicking the View tab for a visual representation of the JSON data.

You can visit the Wikipedia article on JSON (JavaScript Object Notation): http://en.wikipedia.org/wiki/JSON#Data_types.2C_syntax_and_example

-6


source







All Articles