当前位置: 首页 > 工具软件 > ArduinoJson > 使用案例 >

ArduinoJson从版本5迁移到版本6对比差异

扶绍辉
2023-12-01

ArduinoJson从版本5迁移到版本6对比差异


对于ArduinoJson 5, JsonArray和JsonObject总是通过引用返回,以强调它们驻留在JsonBuffer中。

  • ArduinoJson 5

对于ArduinoJson 5, JsonArray和JsonObject总是通过引用返回,以强调它们驻留在JsonBuffer中。

// ArduinoJson 5
JsonObject& obj = ...
  • ArduinoJson 6

ArduinoJson 6通过返回包装器类:JsonArray、JsonObject和JsonVariant简化了这一点。但是要小心,这些对象的内存仍然保存在其他地方,正如我们将看到的。

// ArduinoJson 6
JsonObject obj = ...

JsonDocument

对于ArduinoJson 5,使用JsonObject或JsonArray作为类成员是非常困难的,因为你必须确保JsonBuffer也留在内存中。技巧是也将JsonBuffer添加为类成员,但这比它应该的要复杂得多。

ArduinoJson 6用JsonDocument的概念替换了JsonBuffer的概念。JsonDocument拥有内存并包含对象树的根。您可以看到JsonDocumentJsonBufferJsonVariant的组合。

  • 由于JsonDocument可以包含任何类型的值,因此需要对其进行强制转换以读取内容。例如:
JsonObject root = doc.as<JsonObject>(); // get the root object

类似地,可以将JsonDocument重新用于保存任何类型的值。这是通过JsonDocument::to()完成的。例如,你可以像这样重置一个JsonDocument来保存一个JsonObject:

JsonObject root = doc.to<JsonObject>(); // clear and replace with a new JsonObject

最后,你可以将一个JsonDocument赋值给另一个JsonDocument以获得深度拷贝:

DynamicJsonDocument doc2 = doc1; // makes a copy

自动转换

大多数情况下,您可以跳过对JsonDocument::to()的调用,因为JsonDocument在第一次调用时自动转换为正确的类型。在下面的例子中,JsonDocument隐式地转换为一个对象:

doc["hello"] = "world";

// The above line is equivalent to:
JsonObject root = doc.to<JsonObject>();
root["hello"] = "world";

在下面的例子中,JsonDocument隐式地转换为一个数组:

doc.add("hello");

// The above line is equivalent to:
JsonArray root = doc.to<JsonArray>();
root.add("hello");

当然,自动转换只在JsonDocument为空时发生。

StaticJsonDocument 和 DynamicJsonDocument

作为JsonBuffer, JsonDocument有两个版本。

  • 第一个是StaticJsonDocument,相当于StaticJsonBuffer:
// ArduinoJson 5
StaticJsonBuffer<256> jb;

// ArduinoJson 6
StaticJsonDocument<256> doc;
  • 第二个是DynamicJsonDocument,相当于DynamicJsonBuffer:
// ArduinoJson 5
DynamicJsonBuffer jb;

// ArduinoJson 6
DynamicJsonDocument doc(1024);

DynamicJsonDocument有一个固定的容量,必须指定给构造函数。与DynamicJsonBuffer不同,DynamicJsonDocument不会自动展开。

deserializeJson() 反序列化

对于ArduinoJson 5,您可以通过调用JsonBuffer::parseObject()或JsonBuffer::parseArray()来调用JSON解析器。

// ArduinoJson 5
JsonObject& obj = jb.parseObject(input);
  • 在ArduinoJson 6中,调用函数deserializeJson()并将JsonDocument和输入作为参数传递。
// ArduinoJson 6
deserializeJson(doc, input);

每次调用deserializeJson()时,都会清除JsonDocument。该特性允许多次重用同一个JsonDocument,这在JsonBuffer中是不可能的。请不要将此视为使用全局JsonDocument的邀请,因为这是一个不优雅且低效的解决方案。

DeserializationError 反序列化错误检测

对于ArduinoJson 5,您使用JsonObject::success()或JsonArray::success()来检查解析是否成功,并且您没有关于哪里出错的信息。

// ArduinoJson 5
JsonObject& obj = jb.parseObject(input);
if (!obj.success()) {
   Serial.println("parseObject() failed");
   return;
}
  • 使用ArduinoJson 6,您可以查看由deserializeJson()返回的DeserializationError。您可以测试单个值,如DeserializationError::InvalidInput或DeserializationError:: nommemory,或者您可以通过调用.c_str()将错误转换为字符串。示例:
// ArduinoJson 6
auto error = deserializeJson(doc, input);
if (error) {
    Serial.print(F("deserializeJson() failed with code "));
    Serial.println(error.c_str());
    return;
}

serializeJson() and serializeJsonPretty()

  • 使用ArduinoJson 5,当你想序列化一个JsonArray或JsonObject到一个JSON文档,你调用JsonArray::printTo()或JsonObject::printTo()。
// ArduinoJson 5
obj.printTo(Serial);
  • 在ArduinoJson 6中,调用serializeJson()函数并传递JsonArray、JsonObject或JsonDocument。
// ArduinoJson 6
serializeJson(doc, Serial);

类似地,您可以调用serializeJsonPretty()来生成经过美化的JSON文档。

measureJson() and measureJsonPretty()

使用ArduinoJson 5,您可以通过调用JsonArray::measureLength()或JsonObject::measureLength()来计算序列化文档的长度。

// ArduinoJson 5
size_t len = obj.measureLength();

在ArduinoJson 6中,可以调用measureJson()。

// ArduinoJson `6`
size_t len = measureJson(doc);

类似地,measureJsonPretty()替换JsonArray::measurePrettyLength()和JsonObject::measureJsonPretty()。

Non-zero-terminated 输入

ArduinoJson 5没有强制输入以零结束,但强烈建议这样做以防止缓冲区溢出。
使用ArduinoJson 6,您可以向deserializeJson()传递一个额外的参数,以指定输入的最大大小。示例:

// ArduinoJson 6
deserializeJson(doc, input, inputSize);

嵌套限制

使用ArduinoJson 5,您可以通过传递一个可选参数给JsonBuffer::parseArray()或JsonBuffer::parseObject()来更改嵌套限制。

// ArduinoJson 5
JsonObject& obj = jb.parseObject(input, 20);
  • 对于ArduinoJson 6,必须将此值传递给deserializeJson(),并将其强制转换为DeserializationOption::NestingLimit:
// ArduinoJson 6
deserializeJson(doc, input, DeserializationOption::NestingLimit(20));

MessagePack消息包

ArduinoJson 6支持MessagePack文档的序列化和反序列化。
但是,它目前不支持MessagePack的以下特性:

bin format
timestamp
  • 要创建MessagePack文档,您可以使用与JSON文档相同的技术,除了调用serializeMsgPack()而不是serializeJson()。
// ArduinoJson 6
serializeMsgPack(doc, Serial);

类似地,要对MessagePack文档进行反序列化,就像对JSON文档进行反序列化一样,只不过调用的是deserializeMsgPack()而不是deserializeJson()。例如:

// ArduinoJson 6
deserializeMsgPack(doc, input);

serialized() 序列化

在ArduinoJson 5中,当您想要插入一个预格式化的JSON块时,您可以调用RawJson()。

// ArduinoJson 5
obj["raw"] = RawJson("[1,2,3]");
  • 在ArduinoJson 6中,您调用serialized(),它做了完全相同的事情,除了它也支持MessagePack和非零结束的字符串。
// ArduinoJson 6
doc["raw"] = serialized("[1,2,3]");

JsonPair

在ArduinoJson 5中,当您枚举JsonObject中的成员时,您将收到一个具有两个成员变量key和value的JsonPair。第一个是const char*,第二个是JsonVariant。

// ArduinoJson 5
for (JsonPair p : obj) {
    const char* key = p.key;
    JsonVariant value = p.value;
    ...
}
  • 在ArduinoJson 6中,JsonPair::key和JsonPair::value是成员函数。此外,key不会返回const char*,而是返回JsonString。你必须调用JsonString::c_str()来获得指针。
// ArduinoJson 6
for (JsonPair p : obj) {
    const char* key = p.key().c_str();
    JsonVariant value = p.value();
    ...
}

copyArray()

使用ArduinoJson 5,您可以轻松地使用JsonArray::copyFrom()和JsonArray::copyTo()在JsonArray和常规数组之间复制值。

int values[] = {1,2,3};

// ArduinoJson 5
arr.copyFrom(values);
arr.copyTo(values);

在6.9版中,必须调用copyArray()。这两种操作只有一个函数。第一个参数是源,第二个是目的地。

int values[] = {1,2,3};

// ArduinoJson 6
copyArray(values, arr);
copyArray(arr, values);

JsonVariant 引用

对于ArduinoJson 5, JsonVariant具有值语义。可以在没有JsonBuffer的情况下创建实例。

// ArduinoJson 5
JsonVariant var = 42;

对于ArduinoJson 6, JsonVariant有引用语义,像JsonArray和JsonObject。你需要一个JsonDocument来初始化一个JsonVariant。

// ArduinoJson 6
JsonVariant var = doc.to<JsonVariant>();
var.set(42);

isNull()

在ArduinoJson 5中,你可以通过调用success()来检查数组或对象是否有效:

// ArduinoJson 5
if (!obj.success()) ...
  • 在ArduinoJson 6中,你可以使用isNull():
// ArduinoJson 6
if (obj.isNull()) ...

isNull()与success()并不完全相反:当值定义为null时,isNull()和success()都返回true。

  • 还要注意,在ArduinoJson 5中,如果值为null,则<const char*=“”>()返回true;在版本6中不再是这种情况。

总结

  • Deserialization 反序列化
// ArduinoJson 5
DynamicJsonBuffer jb;
JsonObject& obj = jb.parseObject(json);
if (!obj.success()) 
  return;
int value = obj["value"];
// ArduinoJson 6
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, json);
if (error)
  return;
int value = doc["value"];
  • Serialization 序列化
// ArduinoJson 5
DynamicJsonBuffer jb;
JsonObject& obj = jb.createObject();
obj["key"] = "value";
obj["raw"] = RawJson("[1,2,3]");
obj.printTo(Serial);
// ArduinoJson 6
DynamicJsonDocument doc(1024);
doc["key"] = "value";
doc["raw"] = serialized("[1,2,3]");
serializeJson(doc, Serial);
 类似资料: