Liam Bonactarian Liam Bonactarian - 6 months ago 20
JSON Question

Read data from json response

I am developing an application with Delphi 10 Seattle.

I am trying to read a value of an item from JSON.

For example :

{
"findCompletedItemsResponse":[
{
"ack":[
"Success"
],
"version":[
"1.13.0"
],
"timestamp":[
"2016-06-02T16:07:36.736Z"
],
"searchResult":[
{
"@count":"2",
"item":[
{
"itemId":[
"172168793372"
],
"title":[
"Nikon D5000 12.3 MP Digital SLR Camera (Body Only with Accessories)"
],
"globalId":[
"EBAY-US"
],
"primaryCategory":[
{
"categoryId":[
"31388"
],
"categoryName":[
"Digital Cameras"
]
}
],
"galleryURL":[
"http:\/\/thumbs1.ebaystatic.com\/m\/mlRCNAriHPzowbSV9Q7ZFAg\/140.jpg"
],
"viewItemURL":[
"http:\/\/www.ebay.com\/itm\/Nikon-D5000-12-3-MP-Digital-SLR-Camera-Body-Only-Accessories-\/172168793372"
],
"paymentMethod":[
"PayPal"
],
"autoPay":[
"false"
],
"postalCode":[
"02806"
],
"location":[
"Barrington,RI,USA"
],
"country":[
"US"
],
"shippingInfo":[
{
"shippingServiceCost":[
{
"@currencyId":"USD",
"__value__":"0.0"
}
],
"shippingType":[
"Free"
],
"shipToLocations":[
"US"
],
"expeditedShipping":[
"true"
],
"oneDayShippingAvailable":[
"false"
],
"handlingTime":[
"2"
]
}
],
"sellingStatus":[
{
"currentPrice":[
{
"@currencyId":"USD",
"__value__":"178.5"
}
],
"convertedCurrentPrice":[
{
"@currencyId":"USD",
"__value__":"178.5"
}
],
"bidCount":[
"13"
],
"sellingState":[
"EndedWithSales"
]
}
],
"listingInfo":[
{
"bestOfferEnabled":[
"false"
],
"buyItNowAvailable":[
"false"
],
"startTime":[
"2016-04-18T18:45:54.000Z"
],
"endTime":[
"2016-04-25T18:45:54.000Z"
],
"listingType":[
"Auction"
],
"gift":[
"false"
]
}
],
"returnsAccepted":[
"false"
],
"condition":[
{
"conditionId":[
"3000"
],
"conditionDisplayName":[
"Used"
]
}
],
"isMultiVariationListing":[
"false"
],
"topRatedListing":[
"false"
]
},
{
"itemId":[
"172200026135"
],
"title":[
"Nikon D5000 12.3 MP Digital SLR Camera (Body Only with Accessories)"
],
"globalId":[
"EBAY-US"
],
"primaryCategory":[
{
"categoryId":[
"31388"
],
"categoryName":[
"Digital Cameras"
]
}
],
"galleryURL":[
"http:\/\/thumbs4.ebaystatic.com\/m\/mlRCNAriHPzowbSV9Q7ZFAg\/140.jpg"
],
"viewItemURL":[
"http:\/\/www.ebay.com\/itm\/Nikon-D5000-12-3-MP-Digital-SLR-Camera-Body-Only-Accessories-\/172200026135"
],
"paymentMethod":[
"PayPal"
],
"autoPay":[
"false"
],
"postalCode":[
"02806"
],
"location":[
"Barrington,RI,USA"
],
"country":[
"US"
],
"shippingInfo":[
{
"shippingServiceCost":[
{
"@currencyId":"USD",
"__value__":"0.0"
}
],
"shippingType":[
"Free"
],
"shipToLocations":[
"US"
],
"expeditedShipping":[
"true"
],
"oneDayShippingAvailable":[
"false"
],
"handlingTime":[
"2"
]
}
],
"sellingStatus":[
{
"currentPrice":[
{
"@currencyId":"USD",
"__value__":"119.49"
}
],
"convertedCurrentPrice":[
{
"@currencyId":"USD",
"__value__":"119.49"
}
],
"bidCount":[
"2"
],
"sellingState":[
"EndedWithSales"
]
}
],
"listingInfo":[
{
"bestOfferEnabled":[
"false"
],
"buyItNowAvailable":[
"false"
],
"startTime":[
"2016-05-10T07:22:34.000Z"
],
"endTime":[
"2016-05-16T19:22:25.000Z"
],
"listingType":[
"Auction"
],
"gift":[
"false"
]
}
],
"returnsAccepted":[
"false"
],
"condition":[
{
"conditionId":[
"3000"
],
"conditionDisplayName":[
"Used"
]
}
],
"isMultiVariationListing":[
"false"
],
"topRatedListing":[
"false"
]
}
]
}
],
"paginationOutput":[
{
"pageNumber":[
"1"
],
"entriesPerPage":[
"100"
],
"totalPages":[
"1"
],
"totalEntries":[
"2"
]
}
]
}
]
}


I only want to extract the price of the listed item on ebay. Which is I guess the
currentPrice
.

How can I extract only the value of the price to a variable?

Answer

This is horrible JSON. Whoever designed this data doesn't understand JSON at all. This JSON is grossly overusing 1-element arrays and string values. Most of the arrays do not belong at all, and JSON has other data types available (booleans, integers, etc).

In any case, you can use Delphi's built-in JSON framework to parse this JSON, eg:

uses
  System.JSON;

var
  json: string;
  obj: TJSONObject;
  completedItems, sresults, items, status, price: TJSONArray;
  I, J, K: Integer;
  currencyId, value: string;
begin
  json := ...; // <-- your JSON string here
  obj := TJSONObject.ParseJSONValue(json, 0) as TJSONObject;
  try
    completedItems := obj.Values['findCompletedItemsResponse'] as TJSONArray;
    for I := 0 to completedItems.Count-1 do
    begin
      sresults := (completedItems.Items[I] as TJSONObject).Values['searchResult'] as TJSONArray;
      for J := 0 to sresults.Count-1 do
      begin
        items := (sresults.Items[J] as TJSONObject).Values['item'] as TJSONArray;
        for K := 0 to items.Count-1 do
        begin
          status := (items.Items[K] as TJSONObject).Values['sellingStatus'] as TJSONArray;
          price := ((status.Items[0] as TJSONObject).Values['currentPrice']) as TJSONArray;
          currencyId := price.Values['@currencyId'].Value;
          value := price.Values['__value__'].Value;
          // use price values as needed...
        end;
      end;
    finally
      obj.Free;
    end;
  end;

Alternatively:

uses
  System.JSON;

var
  json: string;
  sreader: TStringReader;
  jreader: TJsonTextReader;
  inCurrentPrice: Boolean;
  currencyId, value: string;
begin
  json := ...; // <-- your JSON string here
  sreader := TStringReader.Create(json);
  try
    jreader := TJsonTextReader.Create(sreader);
    try
      inCurrentPrice := False;
      while jreader.Read do
      begin
        case jreader.TokenType of
          TJsonToken.PropertyName: begin
            if inCurrentPrice then
            begin
              if jreader.Value.AsString = 'currencyId' then begin
                currencyId := jreader.ReadAsString;
              end
              else if jreader.Value.AsString = '__value__' then begin
                value := jreader.ReadAsString;
              end;
            end
            else if jreader.Value.AsString = 'currentPrice' then
            begin
              currencyId := '';
              value := '';
              inCurrentPrice := True;
            end;
          end;
          TJsonToken.EndArray: begin
            if inCurrentPrice then
            begin
              inCurrentPrice := False;
              // use currency values as needed...
            end;
          end;
        end;
      end;
    finally
      jreader.Free;
    end;
  finally
    sreader.Free;
  end;
end;