example to send a JSON to a Socket.io server
Hi, for anyone looking for an example to read a JSON from a file, and send it over as a sio::message -
I have a working setup where JSON is successfully sent over to a Node.js server (through SSL) running Socket.io.
Thought I'd share this. I'm using the awesome nlohmann/json library.
Given the socket is already open and connected,
0. Includes
#include <json.hpp> // using nlohmann's json library
using namespace nlohmann;
1. Converting functions
These functions traverse the json object and recursively convert the whole object into a ready-to-send sio::message::ptr object
sio::message::ptr createObject(json o)
{
sio::message::ptr object = object_message::create();
for (json::iterator it = o.begin(); it != o.end(); ++it)
{
auto key = it.key();
auto v = it.value();
if (v.is_boolean())
{
object->get_map()[key] = bool_message::create(v.get<bool>());
}
else if (v.is_number_integer())
{
object->get_map()[key] = int_message::create(v.get<int>());
}
else if (v.is_string())
{
object->get_map()[key] = string_message::create(v.get<std::string>());
}
else if (v.is_array())
{
json childObject = v;
object->get_map()[key] = createArray(v);
}
else if (v.is_object())
{
json childObject = v;
object->get_map()[key] = createObject(childObject);
}
}
return object;
}
sio::message::ptr createArray(json o)
{
sio::message::ptr array = array_message::create();
for (json::iterator it = o.begin(); it != o.end(); ++it) {
auto v = it.value();
if (v.is_boolean())
{
array->get_vector().push_back(bool_message::create(v.get<bool>()));
}
else if (v.is_number_integer())
{
array->get_vector().push_back(int_message::create(v.get<int>()));
}
else if (v.is_string())
{
array->get_vector().push_back(string_message::create(v.get<string>()));
}
else if (v.is_array())
{
array->get_vector().push_back(createArray(v));
}
else if (v.is_object())
{
array->get_vector().push_back(createObject(v));
}
}
return array;
}
2. JSON reading and emitting code
Now using the converting functions, it's child's play to convert and send the JSON!
// load json
std::ifstream ifs("animation.json");
json animation = json::parse(ifs);
// do stuff with json
// convert and emit
sio::message::ptr object = createObject(animation);
h.socket()->emit("animation", object);
Thanks a lot!
Just 2 hints for other people wanting to use your solution :
- make sure to use the latest version of json.hpp (the one from github : https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp) and not the old one that is in the test folder of socket.io-client-cpp)
- you need to add forward declaration for the second function, as it is used by the first one
EDIT : and if you want to be able to send foating point numbers as well, you should add the following lines in the first function :
else if (v.is_number_float())
{
object->get_map()[key] = double_message::create(v.get<double>());
}
Hi ! Thanks a lot for this !
Would you have any example the other way around, converting from sio::message to json ?
Here is my implementation of the sio::message::ptr -> nlohmann::json function, hope it can help people, I think it makes sense to have alongside the previous functions.
/** @brief Converts an sio::message:ptr object into nlohmann::json
*
* @param sio
* @return nlohmann::json
*/
nlohmann::json createJson(sio::message::ptr sio)
{
// return json
nlohmann::json json;
try
{
// browse flags, we consider it can only be array/vector or object/map
if (sio->get_flag() == sio::message::flag_array)
{
for (int i = 0; i < int(sio->get_vector().size()); ++i)
{
if (sio->get_vector()[i]->get_flag() == sio::message::flag_object ||
sio->get_vector()[i]->get_flag() == sio::message::flag_array)
json[i] = this->createJson(sio->get_vector()[i]);
else if (sio->get_vector()[i]->get_flag() == sio::message::flag_integer)
{
json[i] = sio->get_vector()[i]->get_int();
}
else if (sio->get_vector()[i]->get_flag() == sio::message::flag_double)
{
json[i] = sio->get_vector()[i]->get_double();
}
else if (sio->get_vector()[i]->get_flag() == sio::message::flag_string)
{
json[i] = sio->get_vector()[i]->get_string();
}
else if (sio->get_vector()[i]->get_flag() == sio::message::flag_boolean)
{
json[i] = (sio->get_vector()[i]->get_bool() ? "true" : "false");
}
else if (sio->get_vector()[i]->get_flag() == sio::message::flag_null)
{
// json[i] = "null"; // do not set json[i] so that it's set to json-null properly
}
else
{
std::cout << "Unknown flag in vector: " << sio->get_flag() << ", i is " << i << std::endl;
}
}
}
else if (sio->get_flag() == sio::message::flag_object)
{
for (auto it = sio->get_map().cbegin(); it != sio->get_map().cend(); ++it)
{
if (it->second->get_flag() == sio::message::flag_object ||
it->second->get_flag() == sio::message::flag_array)
json[it->first] = this->createJson(it->second);
else if (it->second->get_flag() == sio::message::flag_integer)
{
json[it->first] = it->second->get_int();
}
else if (it->second->get_flag() == sio::message::flag_double)
{
json[it->first] = it->second->get_double();
}
else if (it->second->get_flag() == sio::message::flag_string)
{
json[it->first] = it->second->get_string();
}
else if (it->second->get_flag() == sio::message::flag_boolean)
{
json[it->first] = it->second->get_bool();
}
else if (it->second->get_flag() == sio::message::flag_null)
{
// json[it->first] = "null"; // do not set json[i] so that it's set to json-null properly
}
else
{
std::cout << "Unknown flag in object: " << sio->get_flag() << ", it first is " << it->first << std::endl;
}
}
}
else
std::cout << "Unknown flag in createJson function: " << sio->get_flag() << std::endl;
}
catch (nlohmann::json::exception &e)
{
std::cout << "JSON exception caught in " << __FUNCTION__ << " (message: " << e.what() << ")" << std::endl;
}
// return
return json;
}