根据字符串递归进入Json对象
Recursively entering Json object based on string
我有以下 json 对象:
{
"ESP_IN_PC_OUT":{
"track":{
"1":{
"mute":{
"type":"LED",
"pins":[4]
}
},
"2":{
"mute":{
"type":"LED",
"pins":[5]
}
}
}
}
}
我要输入对象,取决于格式为“/index1/index2/index3 ...”的字符串(该字符串是OSC消息的地址)。例如,“/track/2/mute”应该 return 一个像这样的 Json 对象:
{
"type":"LED",
"pins":[5]
}
这样我就可以访问类型、引脚数组和一些稍后将实现的其他值。
我在 ESP8266 上使用 Arduino JSON library。这是我试过的代码:
#include <ArduinoJson.h>
char *jsonstr = "{\n \"ESP_IN_PC_OUT\":{\n \"track\":{\n \"1\":{\n \"mute\":{\n \"type\":\"LED\",\n \"pins\":[4]\n }\n },\n \"2\":{\n \"mute\":{\n \"type\":\"LED\",\n \"pins\":[5]\n }\n }\n }\n },\n\n\n \"ESP_OUT_PC_IN\":{\n \"analog\":{\n },\n \"digital\":{\n \"16\":\"/track/1/mute\"\n }\n }\n}";
void setup() {
Serial.begin(115200);
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(jsonstr);
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
Serial.println((const char*) root["ESP_IN_PC_OUT"]["track"]["2"]["mute"]["type"]); // prints "LED"
Serial.println();
char *address = "/track/2/mute"; // _____Interesting part_____
char *tmp = strtok(address,"/");
JsonObject& tmpJson = root["ESP_IN_PC_OUT"];
bool success = true;
while(tmp != NULL && success == true){
Serial.println(tmp);
if(tmpJson.containsKey(tmp)){
tmpJson = tmpJson[tmp]; // Error: use of deleted function 'ArduinoJson::JsonObject& ArduinoJson::JsonObject::operator=(const ArduinoJson::JsonObject&)'
tmp = strtok(NULL,"/");
} else {
success = false;
}
}
if(success == true){
Serial.println((const char*)tmpJson["type"]);
} else {
Serial.println("Address not found");
}
}
void loop() {
}
但是,这给了我以下错误信息:
JSON_OSC_settings2:26: error: use of deleted function 'ArduinoJson::JsonObject& ArduinoJson::JsonObject::operator=(const ArduinoJson::JsonObject&)'
tmpJson = tmpJson[tmp];
^
In file included from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.hpp:12:0,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\JSON_OSC_settings2\JSON_OSC_settings2.ino:1:
C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson/JsonObject.hpp:38:7: note: 'ArduinoJson::JsonObject& ArduinoJson::JsonObject::operator=(const ArduinoJson::JsonObject&)' is implicitly deleted because the default definition would be ill-formed:
class JsonObject : public Internals::JsonPrintable<JsonObject>,
^
In file included from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson/JsonArray.hpp:13:0,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.hpp:11,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\JSON_OSC_settings2\JSON_OSC_settings2.ino:1:
C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson/Internals/ReferenceType.hpp:32:18: error: 'ArduinoJson::Internals::ReferenceType& ArduinoJson::Internals::ReferenceType::operator=(const ArduinoJson::Internals::ReferenceType&)' is private
ReferenceType& operator=(const ReferenceType&);
^
In file included from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.hpp:12:0,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\JSON_OSC_settings2\JSON_OSC_settings2.ino:1:
C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson/JsonObject.hpp:38:7: error: within this context
class JsonObject : public Internals::JsonPrintable<JsonObject>,
^
exit status 1
use of deleted function 'ArduinoJson::JsonObject& ArduinoJson::JsonObject::operator=(const ArduinoJson::JsonObject&)'
我该如何解决这个问题?我可以采取什么不同的方法?
我不是 C 开发人员,但可以帮助您的是 »JSONPath«,它与 JSON 的 xPath 对应。也许您可以找到可以做到这一点的图书馆。
This好像是类似的东西
为了指向sub-object,你可以简单地使用:
JsonObject& tmpJson = root["ESP_IN_PC_OUT"]["track"]["2"]["mute"];
接下来你可以检查这个 sub-object 是否存在,将它与 JsonObject::invalid
进行比较,如下所示:
bool success = (tmpJson != JsonObject::invalid());
if(success == true){
Serial.println((const char*)tmpJson["type"]);
} else {
Serial.println("Address not found");
}
如果路径的一部分不存在,operator[]
将 return 引用 JsonObject::invalid
然后访问其 child 也将 return引用 JsonObject::invalid
,那么迭代到不存在的 child.
是安全的
我编写了一个函数来解析简单的 json 路径字符串并从 json 字符串中提取一个值。有关详细信息,请参阅 https://github.com/bblanchon/ArduinoJson/issues/821。
我最近将它改编为 ArduinoJson6 - 我不得不承认我不是 c++ 的人,所以请怜悯我的代码:
// parse jsonPaths like $.foo[1].bar.baz[2][3].value equals to foo[1].bar.baz[2][3].value
String parseJson(char* jsonString, char *jsonPath) {
Serial.printf("parsing String '%s'\n", jsonString);
String jsonValue;
DynamicJsonDocument jsonBuffer(64000); // fixme!!!!
DeserializationError err = deserializeJson(jsonBuffer, jsonString);
JsonVariant root = jsonBuffer.as<JsonVariant>();
JsonVariant element = root;
if (!err) {
// parse jsonPath and navigate through json object:
char pathElement[40];
int pathIndex = 0;
Serial.printf("parsing Path '%s'\n", jsonPath);
for (int i = 0; jsonPath[i] != '[=10=]'; i++){
if (jsonPath[i] == '$') {
element = root;
} else if (jsonPath[i] == '.') {
if (pathIndex > 0) {
pathElement[pathIndex++] = '[=10=]';
//printf("pathElement '%s'\n", pathElement);
pathIndex = 0;
element = element[pathElement];
if (element == nullptr) {
Serial.printf("failed to parse key %s\n", pathElement);
return nullptr;
}
}
} else if ((jsonPath[i] >= 'a' && jsonPath[i] <= 'z')
|| (jsonPath[i] >= 'A' && jsonPath[i] <= 'Z')
|| (jsonPath[i] >= '0' && jsonPath[i] <= '9')
|| jsonPath[i] == '-' || jsonPath[i] == '_'
) {
pathElement[pathIndex++] = jsonPath[i];
} else if (jsonPath[i] == '[') {
if (pathIndex > 0) {
pathElement[pathIndex++] = '[=10=]';
// printf("pathElement '%s'\n", pathElement);
pathIndex = 0;
element = element[pathElement];
if (element == nullptr) {
Serial.printf("failed in parsing key %s\n", pathElement);
return nullptr;
}
}
} else if (jsonPath[i] == ']') {
pathElement[pathIndex++] = '[=10=]';
int arrayIndex = strtod(pathElement, NULL);
// printf("index '%s' = %d\n", pathElement, arrayIndex);
pathIndex = 0;
element = element[arrayIndex];
if (element == nullptr) {
Serial.printf("failed in parsing index %d\n", arrayIndex);
return nullptr;
}
}
}
// final token if any:
if (pathIndex > 0) {
pathElement[pathIndex++] = '[=10=]';
// printf("pathElement '%s'\n", pathElement);
pathIndex = 0;
element = element[pathElement];
if (element == nullptr) {
Serial.printf("failed in parsing key %s\n", pathElement);
return nullptr;
}
}
jsonValue = element.as<String>();
} else {
jsonValue = nullptr;
}
return jsonValue;
}
我有以下 json 对象:
{
"ESP_IN_PC_OUT":{
"track":{
"1":{
"mute":{
"type":"LED",
"pins":[4]
}
},
"2":{
"mute":{
"type":"LED",
"pins":[5]
}
}
}
}
}
我要输入对象,取决于格式为“/index1/index2/index3 ...”的字符串(该字符串是OSC消息的地址)。例如,“/track/2/mute”应该 return 一个像这样的 Json 对象:
{
"type":"LED",
"pins":[5]
}
这样我就可以访问类型、引脚数组和一些稍后将实现的其他值。
我在 ESP8266 上使用 Arduino JSON library。这是我试过的代码:
#include <ArduinoJson.h>
char *jsonstr = "{\n \"ESP_IN_PC_OUT\":{\n \"track\":{\n \"1\":{\n \"mute\":{\n \"type\":\"LED\",\n \"pins\":[4]\n }\n },\n \"2\":{\n \"mute\":{\n \"type\":\"LED\",\n \"pins\":[5]\n }\n }\n }\n },\n\n\n \"ESP_OUT_PC_IN\":{\n \"analog\":{\n },\n \"digital\":{\n \"16\":\"/track/1/mute\"\n }\n }\n}";
void setup() {
Serial.begin(115200);
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(jsonstr);
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
Serial.println((const char*) root["ESP_IN_PC_OUT"]["track"]["2"]["mute"]["type"]); // prints "LED"
Serial.println();
char *address = "/track/2/mute"; // _____Interesting part_____
char *tmp = strtok(address,"/");
JsonObject& tmpJson = root["ESP_IN_PC_OUT"];
bool success = true;
while(tmp != NULL && success == true){
Serial.println(tmp);
if(tmpJson.containsKey(tmp)){
tmpJson = tmpJson[tmp]; // Error: use of deleted function 'ArduinoJson::JsonObject& ArduinoJson::JsonObject::operator=(const ArduinoJson::JsonObject&)'
tmp = strtok(NULL,"/");
} else {
success = false;
}
}
if(success == true){
Serial.println((const char*)tmpJson["type"]);
} else {
Serial.println("Address not found");
}
}
void loop() {
}
但是,这给了我以下错误信息:
JSON_OSC_settings2:26: error: use of deleted function 'ArduinoJson::JsonObject& ArduinoJson::JsonObject::operator=(const ArduinoJson::JsonObject&)'
tmpJson = tmpJson[tmp];
^
In file included from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.hpp:12:0,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\JSON_OSC_settings2\JSON_OSC_settings2.ino:1:
C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson/JsonObject.hpp:38:7: note: 'ArduinoJson::JsonObject& ArduinoJson::JsonObject::operator=(const ArduinoJson::JsonObject&)' is implicitly deleted because the default definition would be ill-formed:
class JsonObject : public Internals::JsonPrintable<JsonObject>,
^
In file included from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson/JsonArray.hpp:13:0,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.hpp:11,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\JSON_OSC_settings2\JSON_OSC_settings2.ino:1:
C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson/Internals/ReferenceType.hpp:32:18: error: 'ArduinoJson::Internals::ReferenceType& ArduinoJson::Internals::ReferenceType::operator=(const ArduinoJson::Internals::ReferenceType&)' is private
ReferenceType& operator=(const ReferenceType&);
^
In file included from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.hpp:12:0,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/ArduinoJson.h:8,
from C:\Users\Pieter\Documents\Arduino\JSON_OSC_settings2\JSON_OSC_settings2.ino:1:
C:\Users\Pieter\Documents\Arduino\libraries\ArduinoJson-master/include/ArduinoJson/JsonObject.hpp:38:7: error: within this context
class JsonObject : public Internals::JsonPrintable<JsonObject>,
^
exit status 1
use of deleted function 'ArduinoJson::JsonObject& ArduinoJson::JsonObject::operator=(const ArduinoJson::JsonObject&)'
我该如何解决这个问题?我可以采取什么不同的方法?
我不是 C 开发人员,但可以帮助您的是 »JSONPath«,它与 JSON 的 xPath 对应。也许您可以找到可以做到这一点的图书馆。
This好像是类似的东西
为了指向sub-object,你可以简单地使用:
JsonObject& tmpJson = root["ESP_IN_PC_OUT"]["track"]["2"]["mute"];
接下来你可以检查这个 sub-object 是否存在,将它与 JsonObject::invalid
进行比较,如下所示:
bool success = (tmpJson != JsonObject::invalid());
if(success == true){
Serial.println((const char*)tmpJson["type"]);
} else {
Serial.println("Address not found");
}
如果路径的一部分不存在,operator[]
将 return 引用 JsonObject::invalid
然后访问其 child 也将 return引用 JsonObject::invalid
,那么迭代到不存在的 child.
我编写了一个函数来解析简单的 json 路径字符串并从 json 字符串中提取一个值。有关详细信息,请参阅 https://github.com/bblanchon/ArduinoJson/issues/821。
我最近将它改编为 ArduinoJson6 - 我不得不承认我不是 c++ 的人,所以请怜悯我的代码:
// parse jsonPaths like $.foo[1].bar.baz[2][3].value equals to foo[1].bar.baz[2][3].value
String parseJson(char* jsonString, char *jsonPath) {
Serial.printf("parsing String '%s'\n", jsonString);
String jsonValue;
DynamicJsonDocument jsonBuffer(64000); // fixme!!!!
DeserializationError err = deserializeJson(jsonBuffer, jsonString);
JsonVariant root = jsonBuffer.as<JsonVariant>();
JsonVariant element = root;
if (!err) {
// parse jsonPath and navigate through json object:
char pathElement[40];
int pathIndex = 0;
Serial.printf("parsing Path '%s'\n", jsonPath);
for (int i = 0; jsonPath[i] != '[=10=]'; i++){
if (jsonPath[i] == '$') {
element = root;
} else if (jsonPath[i] == '.') {
if (pathIndex > 0) {
pathElement[pathIndex++] = '[=10=]';
//printf("pathElement '%s'\n", pathElement);
pathIndex = 0;
element = element[pathElement];
if (element == nullptr) {
Serial.printf("failed to parse key %s\n", pathElement);
return nullptr;
}
}
} else if ((jsonPath[i] >= 'a' && jsonPath[i] <= 'z')
|| (jsonPath[i] >= 'A' && jsonPath[i] <= 'Z')
|| (jsonPath[i] >= '0' && jsonPath[i] <= '9')
|| jsonPath[i] == '-' || jsonPath[i] == '_'
) {
pathElement[pathIndex++] = jsonPath[i];
} else if (jsonPath[i] == '[') {
if (pathIndex > 0) {
pathElement[pathIndex++] = '[=10=]';
// printf("pathElement '%s'\n", pathElement);
pathIndex = 0;
element = element[pathElement];
if (element == nullptr) {
Serial.printf("failed in parsing key %s\n", pathElement);
return nullptr;
}
}
} else if (jsonPath[i] == ']') {
pathElement[pathIndex++] = '[=10=]';
int arrayIndex = strtod(pathElement, NULL);
// printf("index '%s' = %d\n", pathElement, arrayIndex);
pathIndex = 0;
element = element[arrayIndex];
if (element == nullptr) {
Serial.printf("failed in parsing index %d\n", arrayIndex);
return nullptr;
}
}
}
// final token if any:
if (pathIndex > 0) {
pathElement[pathIndex++] = '[=10=]';
// printf("pathElement '%s'\n", pathElement);
pathIndex = 0;
element = element[pathElement];
if (element == nullptr) {
Serial.printf("failed in parsing key %s\n", pathElement);
return nullptr;
}
}
jsonValue = element.as<String>();
} else {
jsonValue = nullptr;
}
return jsonValue;
}