nlohmann's json library syntax error while parsing - c++

I have tried many different ways of doing this but it keeps giving me the same exact error.
std::string username = "Lethal";
std::string password = "test123";
std::ifstream f("DBs/test.json");
json data = json::parse(f);
data["username"] = username;
data["password"] = password;
terminate called after throwing an instance of 'nlohmann::detail::parse_error'
what(): [json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpect
ed end of input; expected '[', '{', or a literal
JSON File:
{
"username": "",
"password": " "
}

Related

how to show a variable in MESSAGE_TEXT in signal query in c++

I am using Signal query to catch errors in my c++ programming:
in the program user has to enter a database name and i check the database if it does not exists I have to return proper error message:
std::string database_name;
std::cin<<database_name;
if(!exists(database_name)){
query="SIGNAL SQLSTATE '42000' SET MYSQL_ERRNO='1049', MESSAGE_TEXT = 'Unknown database';";
}
how can I print the database_name variable after Unknown database?
You can format the string using
query = std::format( "... MESSAGE_TEXT = 'Unknown database {}'", database_name );
This will replace {} with the first string argument (database_name)
Or you could use a string stream like
std::ostringstream ss;
ss << "... MESSAGE_TEXT = 'Unknown database '" << database_name << "'";
query = ss.str();

Illegal unquoted character ((CTRL-CHAR, code 10))

I’m having issue consuming REST API. Below is my rest client. It fails at the service call with error:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Illegal unquoted character ((CTRL-CHAR, code 10)): has to be escaped using backslash to be included in string value; nested exception is com.fasterxml.jackson.core.JsonParseException: Illegal unquoted character ((CTRL-CHAR, code 10)): has to be escaped using backslash to be included in string value
at [Source: java.io.PushbackInputStream#62a8dd06; line: 11, column: 55]
When I use the same json string (printed in the log) in postman, it works. It fails when I fire the request from my client.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Authorization", "Basic " + base64Creds);
try {
request = mapper.constructRequest(txnRequest, params);
logger.debug(method + " Request: " + request);
ObjectMapper map = new ObjectMapper();
logger.debug(method + " Request in json format: " +
map.writeValueAsString(request));
myRequest = new HttpEntity<MyRequest>(request, headers);
response = restTemplate.exchange(url, HttpMethod.POST, myRequest, MyResponse.class);
logger.debug(method + " response: " + response);
} catch(Exception ex) {
ex.printStackTrace();
}
Any help is much appreciated.
I switched to traditional HttpURLConnection to make this work. In this way, I'm able to set the input and output format with utf-8 and it worked. I tried to do the same with rest template, but the issue was persisting. So, I'd to switch my client implementation to HttpURLConnection

string_view points to another string

I'm using Boost 1.70 and found a rather puzzling issue where sometimes boost::string_view seems to point to another string.
This is the function call where a boost::string_view is created as follows:
boost::beast::string_view message = "The resource '" + target.to_string() + "' was not found.";
return prepareError(req, message, beast_http::status::not_found);
And this is the prepareError() method which gets called where something really odd happens. The fist version uses message.to_string() while constructing a string variable:
template<class Body, class Allocator>
beast_http::response<beast_http::string_body> prepareError(beast_http::request<Body, beast_http::basic_fields<Allocator>>& req,
boost::beast::string_view message, beast_http::status statusCode) {
beast_http::response<beast_http::string_body> res{statusCode, req.version()};
res.set(beast_http::field::server, SERVER_VERSION_STRING);
res.set(beast_http::field::content_type, MIMETYPE_JSON);
if (_allowCrossOrigin) {
res.set(beast_http::field::access_control_allow_origin, "*");
}
res.keep_alive(req.keep_alive());
int sc = (int)statusCode;
std::string json = std::string("{\n error_code:") +
std::to_string(sc) + std::string(",\n") +
std::string(" error_description:\"") +
message.to_string() + std::string("\"\n}");
res.body() = json;
res.prepare_payload();
return res;
}
This json variable will contain the following string for example:
Printing description of json:
(std::__1::string) json = "{\n error_code:404,\n error_description:\"{\n error_code:404,\n error_descript\"\n}"
This is really odd. In the debugger the message variable contains an empty string. And as you can see from the method call this should not be the expected result for that string.
This is the same method with the only difference that there is a temporary assignment of the message variable, which is a string_view, to a std::string.
template<class Body, class Allocator>
beast_http::response<beast_http::string_body> prepareError(beast_http::request<Body, beast_http::basic_fields<Allocator>>& req,
boost::beast::string_view message, beast_http::status statusCode) {
beast_http::response<beast_http::string_body> res{statusCode, req.version()};
res.set(beast_http::field::server, SERVER_VERSION_STRING);
res.set(beast_http::field::content_type, MIMETYPE_JSON);
if (_allowCrossOrigin) {
res.set(beast_http::field::access_control_allow_origin, "*");
}
res.keep_alive(req.keep_alive());
int sc = (int)statusCode;
std::string msg = message.to_string();
std::string json = std::string("{\n error_code:") +
std::to_string(sc) + std::string(",\n") +
std::string(" error_description:\"") +
msg + std::string("\"\n}");
res.body() = json;
res.prepare_payload();
return res;
}
This gives the expected string:
Printing description of json:
(std::__1::string) json = "{\n error_code:404,\n error_description:\"The resource '/zones' was not found.\"\n}"
Your error comes from
boost::beast::string_view message = "The resource '" + target.to_string() + "' was not found.";
You create a temporary string on the right hand side, and set the view to point to it. After the line ends, that temporary string is destroyed and your view now points to invalid memory.
What you need to do is pass the temporary directly to the function, like this:
return prepareError(req, "The resource '" + target.to_string() + "' was not found.", beast_http::status::not_found);
Or, capture the result into a std::string variable, and then pass that to the function.
Error is from:
boost::beast::string_view message = "The resource '" + target.to_string() + "' was not found.";
You build a temporary string which end at end of the statement.
So you have dangling view next line.
You have to build string there directly.

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}";

C++REST SDK, parse JSON that contains (0xEF 0xBF 0xBF) character

I have a REST API that returns a string with files metadata. Among those files I have one that has "￿" (0xEF0xBF0xBF, link) character in name. When I try to parse such a response I get exception that says:
e = {_message="* Line 1, Column 13 Syntax error: Malformed string literal" }
This is the string I'm trying to parse:
{"files":[["Thunderbolt ￿Gigabit￿ Ethernet ￿Adapter.txt",["bc288518-c426-4dbd-9600-a213a35d1c04",1447772221866,9,"Bartosz","Siewior"]],["System.Windows.Interactivity.dll",["56ce759b-019b-4723-8fca-7af877908971",1440507238241,55904,"Bartosz","Siewior"]]],"folderPermission":[["MODIFY"]],"directories":[]}
The code I'm using to receive and parse the string:
// ...
client.request(request).then([&](web::http::http_response response) {
status_code = response.status_code();
//response.extract_json(true).then([&](pplx::task<web::json::value> previousTask) {
response.extract_string().then([&](pplx::task<utility::string_t> previousTask) {
try {
utility::string_t str_response = previousTask.get();
web::json::value root;
root = web::json::value::parse(str_response);
}
catch (const web::http::http_exception& e) {
std::wstringstream ss;
ss << e.what();
str_response = ss.str();
}
catch (const web::json::json_exception& e) {
std::wstringstream ss;
ss << e.what();
str_response = ss.str();
}
TaskExecutionData data = { task.id, status_code, str_response.c_str() };
callback(data);
}).wait();
}).wait();
VS2013 JSON Visualizer can parse and show the result properly: VS_json_visualizer
I've tried C++REST version 2.5.0 and 2.6.0, neither of them is able to parse that string... Do you have any ides?
Answer from Casablanca's team:
The issue is that on windows we parse using UTF16 and the particular character you're having issues with maps to 0xFFFF. This is also the character returned by std::char_traits::eof(), so we detect the code point as an "end of stream" signal and terminate the parse appropriately.
The UTF8 parser should not have these issues, so as a workaround you can probably do something similar to how the current web::json::value::parse() function works in json_parsing.cpp:1245, except using char as the template parameter instead of utility::char_t.