Arduinojson: Function to resolve a JSON path composed of several keys

Created on 20 Feb 2021  ·  5Comments  ·  Source: bblanchon/ArduinoJson

I want to deserialize and get value by this way but it doesn't work.

const char data[] = R"=({"x1":"1","x2":"2"})=";

int8_t value(const char* data, JsonDocument& jsonDoc, JsonVariant key)
{
    deserializeJson(jsonDoc, data);

    return key.as<int8_t>();
}

int8_t x = value(data, jsonDoc, jsonDoc["x2"].to< JsonVariant >());
Serial.print("x : "); Serial.println(x);

// Output x : 1

Question 1 -> Why Output (x) = 1 and not 2
Question 2 -> How to do to have Output (x) = 2

Very very good library, thank you !
Sorry for my english, i speak french

question

Most helpful comment

Hi @sorokolokarim,

Doing so require a recursive function with a template parameter pack, like so:

template <typename Key>
JsonVariantConst resolvePath(JsonVariantConst variant, Key key) {
  return variant[key];
}

template <typename Key, typename... Tail>
JsonVariantConst resolvePath(JsonVariantConst variant, Key key, Tail... tail) {
  return resolvePath(variant[key], tail...);
}

template <typename T, typename... Keys>
T value(const char* json, Keys... keys) {
  DynamicJsonDocument doc(4096);
  deserializeJson(doc, json);
  return resolvePath(doc, keys...).template as<T>();
}

const char data[] = R"=( {"a": {"b": {"x2": 2}}})=";
int8_t x = value<int8_t>(data, "a", "b", "x2"); // 2

I know this looks complicated, but it is a common pattern.
BONUS: it works with arrays as well :-)

Demo: https://wandbox.org/permlink/PgICTZ1nIjAULTKO

Best regards,
Benoit

All 5 comments

Hi @sorokolokarim,

It looks like you want something like this:

template<typename T>
T value(const char* json, const char* key)
{
   DynamicJsonDocument doc(4096);
   deserializeJson(doc, json);
   return doc[key].as<T>();
}

const char data[] = R"=({"x1":"1","x2":"2"})=";
int8_t x = value<int8_t>(data, "x2");

This function works with all types except const char*, but you can use String instead.

Best regards,
Benoit

@bblanchon
Thank for your fast response. But effectively the document is biggest, this is just an exemple.

Question -> Is there a method that can give me the possibility from a function to insert an indefinite number of parameter and that then I will use to retrieve a value or values ​​from the json document?

Example : (something like this)

template<typename T>
T value(const char* json, const char* key, ...)
{
   DynamicJsonDocument doc(4096);
   deserializeJson(doc, json);
   return doc[key][...].as<T>();
}
const char data[] = R"=( {"a": {"b": {"x2": 2}}})=";
expected result 1 : 
int8_t x = value<int8_t>(data, "c", "d"); // 5

expected result 2 : 
int8_t x = value<int8_t>(data, "a", "b", "x2"); // 2

I'm still a beginner and I have a hard time doing something like this.

Thank you very much for the helping hand.
Thank you

Hi @sorokolokarim,

Doing so require a recursive function with a template parameter pack, like so:

template <typename Key>
JsonVariantConst resolvePath(JsonVariantConst variant, Key key) {
  return variant[key];
}

template <typename Key, typename... Tail>
JsonVariantConst resolvePath(JsonVariantConst variant, Key key, Tail... tail) {
  return resolvePath(variant[key], tail...);
}

template <typename T, typename... Keys>
T value(const char* json, Keys... keys) {
  DynamicJsonDocument doc(4096);
  deserializeJson(doc, json);
  return resolvePath(doc, keys...).template as<T>();
}

const char data[] = R"=( {"a": {"b": {"x2": 2}}})=";
int8_t x = value<int8_t>(data, "a", "b", "x2"); // 2

I know this looks complicated, but it is a common pattern.
BONUS: it works with arrays as well :-)

Demo: https://wandbox.org/permlink/PgICTZ1nIjAULTKO

Best regards,
Benoit

Hi @bblanchon 🥇
Thank you very very very much !!! Tu me sauves enormement avec cette solution ! You are a master !! I hope on day get your level or more :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nardev picture nardev  ·  5Comments

timpur picture timpur  ·  5Comments

HilalAH picture HilalAH  ·  3Comments

DeltaVetal26 picture DeltaVetal26  ·  3Comments

loewekordel picture loewekordel  ·  4Comments