json::value v[L"responseData"] - error (there is no operator "[]")

Sep 3, 2014 at 7:15 PM
Edited Sep 3, 2014 at 7:17 PM
I never before use C++ REST and json and found an example of use in this blog - [http://mariusbancila.ro/blog/2013/08/02/cpp-rest-sdk-in-visual-studio-2013 /]
(C++ REST SDK in Visual Studio 2013)

there is code:
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/json.h>
 
#include <iostream>
 
using namespace utility;
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace concurrency::streams;
 
using namespace std;
 
void print_search_results(json::value const & value)
{
   if(!value.is_null())
   {
      auto response = value[L"responseData"];
      auto results = response[L"results"];
      for(auto const & p : results)
      {
         auto o = p.second;
         auto url = o[L"url"];
         auto title = o[L"titleNoFormatting"];
 
         wcout << title.as_string() << endl << url.as_string() << endl << endl;
      }
   }
}
 
void search_and_print(wstring const & searchTerm, int resultsCount)
{
   http_client client(U("https://ajax.googleapis.com/ajax/services/search/web"));
 
   // build the query parameters
   auto query =  uri_builder()
      .append_query(L"q", searchTerm)
      .append_query(L"v", L"1.0")
      .append_query(L"rsz", resultsCount)
      .to_string();
 
   client
      // send the HTTP GET request asynchronous
      .request(methods::GET, query)
      // continue when the response is available
      .then([](http_response response) -> pplx::task<json::value>
      {
         // if the status is OK extract the body of the response into a JSON value
         // works only when the content type is application\json
         if(response.status_code() == status_codes::OK)
         {
            return response.extract_json();
         }
 
         // return an empty JSON value
         return pplx::task_from_result(json::value());
      })
      // continue when the JSON value is available
      .then([](pplx::task<json::value> previousTask)
      {
         // get the JSON value from the task and display content from it
         try
         {
            json::value const & v = previousTask.get();
            print_search_results(v);
         }
         catch (http_exception const & e)
         {
            wcout << e.what() << endl;
         }
      })
      .wait();
}

int main(int argc, char *args[])
{
   search_and_print(L"marius bancila", 5);
 
   return 0;
}
but I can't build it!
error on
auto response = value[L"responseData"];
what's wrong??
Coordinator
Sep 3, 2014 at 7:37 PM
Hi togemura,

This is code from an older version of the C++ Rest SDK, 1.0 to be exact. In our 2.0.0 release we make a few breaking API changes to the JSON library which you are hitting. First of which is we removed the 'const' operator[] overload because we felt it was incorrect. The operator[] has semantics of inserting a null value if one doesn't already exist. The replacement for 'const' is to use the json::value::at() method instead, as this more closely follows the design of the C++ standard library and will throw an exception if the specified field doesn't exist. The second change is we no longer support iterating over json objects and arrays directly from the json::value class. New classes called json::object and json::array were introduced that support iteration more efficiently and in an easier to use manor. To access, use json::value::as_object() and json::value::as_array().

I didn't run it but here is your code made with the changes and it now compiles:
void print_search_results(json::value const & value)
{
    if (!value.is_null())
    {
        auto response = value.at(L"responseData");
        auto results = response[L"results"];

        // iteration is supported not directly on json::value but on 
        // json::object and json::array. Use json::value::as_object() and json::value::as_array().
        for (auto const & o : results.as_array())
        {
            auto url = o.at(L"url");
            auto title = o.at(L"titleNoFormatting");

            std::wcout << title.as_string() << std::endl << url.as_string() << std::endl << std::endl;
        }
    }
}

void search_and_print(std::wstring const & searchTerm, int resultsCount)
{
    http_client client(U("https://ajax.googleapis.com/ajax/services/search/web"));

    // build the query parameters
    auto query = uri_builder()
        .append_query(L"q", searchTerm)
        .append_query(L"v", L"1.0")
        .append_query(L"rsz", resultsCount)
        .to_string();

    client
        // send the HTTP GET request asynchronous
        .request(methods::GET, query)
        // continue when the response is available
        .then([](http_response response) -> pplx::task<json::value>
    {
        // if the status is OK extract the body of the response into a JSON value
        // works only when the content type is application\json
        if (response.status_code() == status_codes::OK)
        {
            return response.extract_json();
        }

        // return an empty JSON value
        return pplx::task_from_result(json::value());
    })
        // continue when the JSON value is available
        .then([](pplx::task<json::value> previousTask)
    {
        // get the JSON value from the task and display content from it
        try
        {
            json::value const & v = previousTask.get();
            print_search_results(v);
        }
        catch (http_exception const & e)
        {
            std::wcout << e.what() << std::endl;
        }
    })
        .wait();
}
I choose to keep the const semantics on your json::value parameter in print_search_results. Another option would have been to not use const and you still could use the operator[], obviously knowing it will insert if the object doesn't exist.

Steve
Marked as answer by togemura on 9/3/2014 at 11:47 AM
Sep 3, 2014 at 7:47 PM
It works!!!!
Thank You Very Very Much!!!! ^__^
Coordinator
Sep 3, 2014 at 7:50 PM
I also recommend you take a look at our documentation, in particular the json reference documentation will help you out.

Steve
Jul 7, 2015 at 8:48 AM
Hi Steve,

In continuation of this post, I want to ask a query related to json.

now, we can iterate through json::value. Then how to retrieve json property name. json value can extracted as u explained above.

for example I have following Json :

{
     "name" : "Pooja" 
      "location" : "India"
      "ld" : 28,
},

and we get json value as val = {"name" : "Pooja"}
and can retrieve value of property "name" as val.at("name").

but I need to get property name too.

Could you please help on this.

Regards.
Pooja
Coordinator
Jul 7, 2015 at 5:44 PM
Hi Pooja,

I think it is better to no repurpose or recycle threads. Please open a new one since this is a completely different discussion than the original. You have to iterate through the individual elements of the JSON object. There you will get the key/value pairs. What exactly are you trying to accomplish that you don't want to iterate through the elements in the JSON object, but don't know the key you are looking for ahead of time?

Steve