Json serializing in C++ (ESP32) - c++

I'm writing some script for ESP32 and struggling to serialize a json.
Used libraries are HTTPClient and ArduinoJson.
String payload = http.getString();
Serial.println(payload);
deserializeJson(result, payload);
const char* usuario = result["user"];
Serial.println("##########");
Serial.println(usuario);
The received payload is:
{"ip":"10.57.39.137","area":"[{\"id\":\"3\",\"text\":\"BOX\"}]","user":"[{\"id\":\"6270\",\"text\":\"ANDRE LARA OLIVEIRA E SILVA\"}]","teamId":6,"id":4,"siteId":2,"userCreate":"100059527","dateCreate":"2020-11-19T08:49:03.957","userUpdate":null,"dateUpdate":null}
I need to retrieve id and text from "user" key. It's fine to deserialize and retrieve user object. But result["user"] returns: [{"id":"6270","text":"ANDRE LARA OLIVEIRA E SILVA"}] to the char array. So it's something like a json nested in an array... and it's not working out to deserialize.
Can anyone help me how to properly get the "id" and "text" values from "user" object?

The library doesn't know the content of that string is valid JSON, so you have re-parse it. This code worked for me on my PC, though I don't have an Arduino to test it on:
auto payload = "..."; // JSON content here
StaticJsonDocument<1024> result;
deserializeJson(result, payload);
auto user = result["user"].as<const char*>();
StaticJsonDocument<256> userObj;
deserializeJson(userObj, user);
auto id = userObj[0]["id"].as<int>();
auto text = userObj[0]["text"].as<const char*>();

"Can anyone help me how to properly get the "id" and "text" values from "user" object?" You can access them with
const char *id = result["user"]["id"];
const char *text = result["user"]["text"];

Try:
const int id = result["user"]["id"];
const char* text = result["user"]["text"];

Related

how to set hash in Postman Pre-Request Script for Marvel API

I have a pre-request script that I gathered from another post on StackOverflow, but I'm still getting invalid credentials.
Attempted to do this just with str_1 but it's not working. Not sure what request.data is supposed to do as it keeps returning NaN. I think that the problem might be there, but still at a loss. I've attempted converting all variables to a string, but that still returned the same error.
URL = https://gateway.marvel.com/v1/public/characters?ts={{timeStamp}}&apikey={{apiKey}}&hash={{hash}}
// Access your env variables like this
var ts = new Date();
ts = ts.getUTCMilliseconds();
var str_1 = ts + environment.apiKey + environment.privateKey;
// Or get your request parameters
var str_2 = request.data["timeStamp"] + request.data["apiKey"];
console.log('str_2 = ' + str_2);
// Use the CryptoJS
var hash = CryptoJS.MD5(str_1).toString();
// Set the new environment variable
pm.environment.set('timeStamp', ts);
pm.environment.set('hash', hash);
{
"code": "InvalidCredentials",
"message": "That hash, timestamp and key combination is invalid."
}
If someone can comment on why this is the solution, I would appreciate it. Here is what the issue was. The order of the hash actually matters. So had to flip the order of pvtkey + pubkey to pubkey + pvtkey. Why is this?
INCORRECT
var message = ts+pubkey+pvtkey;
var a = CryptoJS.MD5(message);
pm.environment.set("hash", a.toString());
CORRECT
var message = ts+pvtkey+pubkey;
var a = CryptoJS.MD5(message);
pm.environment.set("hash", a.toString());
I created in Android Studio, a new java class named MD5Hash, following the steps of https://javarevisited.blogspot.com/2013/03/generate-md5-hash-in-java-string-byte-array-example-tutorial.html
I just simplified his (her) code, only to use it with Java utility MessageDigest
public class MD5Hash {
public static void main(String args[]) {
String publickey = "abcdef"; //your api key
String privatekey = "123456"; //your private key
Calendar calendar=Calendar.getInstance();
String stringToHash = calendar
.getTimeInMillis()+ privatekey + publickey;
System.out.println("hash : " + md5Java(stringToHash));
System.out.println("ts : "+ calendar.getTimeInMillis());
}
public static String md5Java(String message){
String digest = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(message.getBytes("UTF-8"));
//converting byte array to Hexadecimal String
StringBuilder sb = new StringBuilder(2*hash.length);
for(byte b : hash){
sb.append(String.format("%02x", b&0xff));
}
digest = sb.toString();
} catch (UnsupportedEncodingException ex) {
} catch (NoSuchAlgorithmException ex) {
}
return digest;
}
}
As you can see, if you copy paste this code, it has a green arrow on the left side of the class declaration, clicking it you can run MD5Hash.main() and you'll have printed in your Run Screen the values for the time (ts) and for the hash.
Then go to verify directly into the internet :
https://gateway.marvel.com/v1/public/characters?limit=20&ts=1574945782067&apikey=abcdef&hash=4bbb5dtf899th5132hjj66

Parsing Json using arduino-mqtt lib

I am trying to use the arduino-mqtt lib.
I have this working sending the json string. The problem comes with trying to parse the string with ArduinioJson. It just returns no value.
I think it may have todo with the pointer reference in the mqttMessageRecived function ( String &payload).
Function called when there is an MQTT message:
void mqttMessageReceived(String &topic, String &payload){
//Example String for test
String json = "{"id" : "100" , "cmd" : "0xff"}";
jsonout(payload);
Serial.println("Sending Static String");
jsonout(json);
Function to parse json input:
void jsonout(String Json){
StaticJsonDocument<200> doc;
//Deserialize the JSON document
DeserializationError error = deserializeJson(doc, Json);
Serial.println("Got String: ");
Serial.println(Json);
// Test if parsing succeeds.
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
const char* id = doc["id"];
const char* cmd = doc["cmd"];
// Print values.
Serial.println(id);
Serial.println(cmd);
}
Non parsed output:
Message from MQTT
Got String:
"{\"id\" : 4 , \"cmd\": \"0xee\"}"
Result = No output from json parse
Non parsed output:
Sending Static String
Got String:
{"id" : "100" , "cmd" : "0xff"}
Result = Output from json parse:
100
0xff
The problem is that - in the response from the server
"{\"id\" : 4 , \"cmd\": \"0xee\"}"
the id field is an integer - not a character array.
So you need to change
const char* id = doc["id"];
to
int id = doc["id"];
(and update your test string to use an int for the ID also).
The server returns a id member that's a Number "id":4, while you are generating a id that's a String "id":"200".
You need to adjust your code to either one. If it's a number (and it seems so), you need to send "id":200 and change your code to get a number:
unsigned id = (double)doc["id"];
// And to generate it:
String json = "{\"id\" : 100 , \"cmd\" : \"0xff\"}";
Also, with JSON, beware of hexadecimal encoding, has it's not converted to number (you have to do it yourself by receiving a const char* and calling sscanf or strtol or ...) and it's not convenient. It's better to use base-10 encoding instead:
String json = "{\"id\" : 100 , \"cmd\" : 255}";

Replacing value of a member in rapidjson

I am currently working on a project in C++ using rapidjson.
My program receives some JSON data on a socket which includes some authentication details. I log the incoming message, but I want to hide the password so it can't be seen in the log file. So I am trying to get the JSON object, and replace each character of the string and put this replaced string back into the json object where the password was.
Below is the code that I have:
rapidjson::Document jsonObject;
jsonObject.Parse(command.c_str());
string method = jsonObject["method"].GetString();
if (jsonObject.HasMember("sshDetails"))
{
Value& sshDetails = jsonObject["sshDetails"];
string sshPassword = sshDetails["sshPassword"].GetString();
for (int i = 0; i < sshPassword.length(); i++)
{
sshPassword[i] = '*';
}
rapidjson::Value::Member* sshPasswordMember = sshDetails.FindMember("sshPassword");
sshPasswordMember->name.SetString(sshPassword.c_str(), jsonObject.GetAllocator());
//Convert it back to a string
rapidjson::StringBuffer buffer;
buffer.Clear();
rapidjson::Writer<rapidjson::StringBuffer>writer(buffer);
Document jsonDoc;
jsonDoc.Accept(writer);
string jsonString = string(buffer.GetString());
I'm getting an error on the following line:
rapidjson::Value::Member* sshPasswordMember = sshDetails.FindMember("sshPassword");
The error I am getting is:
No suitable conversion function from rapidjson::GenericMemberIterator<false, rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CtrlAllocator>> to rapidjson::GenericMember::UTF8<char>, myProject...SocketProcessor.cpp
rapidjson::MemoryPoolAllocator<rapidjson::CtrlAllocator>>*exists
I took the above from an example on another question on SO which was an accepted answer from rapidjson - change key to another value, so what am I missing.
I've managed to find the answer to this with a bit of playing round and luck.
I changed
rapidjson::Value::Member* sshPasswordMember = sshDetails.FindMember("sshPassword");
sshPasswordMember->name.SetString(sshPassword.c_str(), jsonObject.GetAllocator());
to be
rapidjson::Value::MemberIterator sshPasswordMember = sshDetails.FindMember("sshPassword");
sshPasswordMember->value.SetString(sshPassword.c_str(), jsonObject.GetAllocator());
using rapidjson in my project I found out that many of such problems can be omitted by the use of auto instead of specifying the type

How to get data from Photon eventContent dictionary

We are receiving this callback using ExitGames Photon Realtime engine when an event is fired
customEventAction(int playerNr,
nByte eventCode,
const ExitGames::Common::Object& eventContent)
If the object is a string we use this code to extract it
ExitGames::Common::JString str =
ExitGames::Common::ValueObject<ExitGames::Common::JString>(eventContent).getDataCopy();
However, the object being sent is a dictionary. It's being sent from the server using BroadcastEvent.
How do we get data out of it ?
We've tried this, but it doesn't make any sense:
ExitGames::Common::Dictionary<byte,ExitGames::Common::Object> pdic
= ExitGames::Common::ValueObject<ExitGames::Common::Dictionary<byte,ExitGames::Common::Object>>(eventContent).getDataCopy();
I've found code to get the data from a hashtable, but that doesn't work either.
thanks
Shaun
ExitGames::Common::Dictionary<nByte, ExitGames::Common::Object> dic = ExitGames::Common::ValueObject<ExitGames::Common::Dictionary<nByte, ExitGames::Common::Object> >(eventContent).getDataCopy();
is absolutely correct and works for me.
The cause of your problem must be inside another line.
When you replace the implementations of sendEvent() and customEventAction() in demo_loadBalancing inside one of the Photon C++ client SDKs with the following snippets, then that demo successfully sends and receives a Dictionary:
send:
void NetworkLogic::sendEvent(void)
{
ExitGames::Common::ValueObject<ExitGames::Common::JString> obj(L"test");
ExitGames::Common::Dictionary<nByte, ExitGames::Common::Object> dic;
dic.put(1, obj);
mLoadBalancingClient.opRaiseEvent(false, dic, 0);
}
receive:
void NetworkLogic::customEventAction(int /*playerNr*/, nByte /*eventCode*/, const ExitGames::Common::Object& eventContent)
{
EGLOG(ExitGames::Common::DebugLevel::ALL, L"");
ExitGames::Common::Dictionary<nByte, ExitGames::Common::Object> dic = ExitGames::Common::ValueObject<ExitGames::Common::Dictionary<nByte, ExitGames::Common::Object> >(eventContent).getDataCopy();
const ExitGames::Common::Object* pObj = dic.getValue(1);
ExitGames::Common::JString str = ExitGames::Common::ValueObject<ExitGames::Common::JString>(pObj).getDataCopy();
mpOutputListener->write(L"received the following string as Dictionary value: " + str);
}
This gives me the following line of output on the receiving client:
received the following string as Dictionary value: test

gsoap c++ android device encoding

8.15,
I can connect my microsoft web service and I can insert record with this service easily.
I get a confirmation code as a response for record insert. But I have a problem with encoding. The response message must like this 1Exa9GwOIO6pP35l4TJ1Bw== but instead of this I get a response like this 4�� u #
When I try this service on a browser I get the expected response as
in 1Exa9GwOIO6pP35l4TJ1Bw==
But when I try it on an android device with gsoap I get a response such as this one 4�� u #
How can I solve this encoding problem?
TheGameSoapProxy service;
_ns1__PlayerRegisterResponse* response = new _ns1__PlayerRegisterResponse();
std::string telNO =m_pEditTel->getText();
std::string telefonIME = "111";
std::string simCardID = "222";
std::string Username = m_pEditName->getText();
std::string takim = Takim.c_str();
_ns1__PlayerRegister* ps = new _ns1__PlayerRegister();
ps->telefonNumarasi = &telNO;
ps->telefonIME = &telefonIME;
ps->simCardID = &simCardID;
ps->Username = &Username;
ps->takim = &takim;
if (service.PlayerRegister(ps, response) == SOAP_OK)
{
string *ptrSonuc = response->PlayerRegisterResult;
CCLog( (char*)ptrSonuc );
}
As per other question here on SO:
add the line below to your typemap.dat file:
xsd__string = | wchar_t* | wchar_t*
And then use wstrings instead of strings.