Json deserializeJson

Bonjour a tous,
Dans mon projet sur ESP32 j'utilise ArduinoJson pour récupérer une horloge hebdomadaire.
donc j'utilise:

if (WiFi.status() == WL_CONNECTED) {
    http.begin(serverName1);
    http.setAuthorization("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
    http.addHeader("Content-Type", "application/json");
    StaticJsonDocument<200> doc;
    doc["encode"] = "text";
    doc["propertyReferences"][0]["type"] = "schedule";
    doc["propertyReferences"][0]["instance"] = 1; //remplacer 1 par commande "horlogez[tiltcirh]"
    doc["propertyReferences"][0]["property"] = "weeklySchedule";
    String requestBody;
    serializeJson(doc, requestBody);
    httpResponseCode = http.POST(requestBody);
    //Serial.println(requestBody);
    if(httpResponseCode == 200){      
    response = http.getString();
    Serial.println(response);

qui me retourne
[{"type":"schedule","instance":1,"property":"weeklySchedule","value":"{{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{06:55:00.00;Boolean:true,18:00:00.00;Null:Null},{06:55:00.00;Boolean:true,17:55:00.00;Null:Null}}"}]

j'ai utiliser assistant arduinojson
qui me sort

JsonDocument filter;
filter.set(true);

JsonDocument doc;

DeserializationError error = deserializeJson(doc, response, DeserializationOption::Filter(filter));

if (error) {
  Serial.print("deserializeJson() failed: ");
  Serial.println(error.c_str());
  return;
}

JsonObject root_0 = doc[0];
const char* root_0_type = root_0["type"]; // "schedule"
int root_0_instance = root_0["instance"]; // 1
const char* root_0_property = root_0["property"]; // "weeklySchedule"
const char* root_0_value = root_0["value"];

mais dans root_0_value tout est en une chaine.
je voulais ranger les donnée de value dans un tableau où chaque ligne c'est un jour (0=lundi..) et les colonnes de 0 à 3 (0 = heure début, 1 = état début, 2 = heure fin, 3 = état fin)

float horl1[7][4] = {
  { 0.0, 0.0, 0.0, 0.0 },
  { 0.0, 0.0, 0.0, 0.0 },
  { 0.0, 0.0, 0.0, 0.0 },
  { 0.0, 0.0, 0.0, 0.0 },
  { 0.0, 0.0, 0.0, 0.0 },
  { 0.0, 0.0, 0.0, 0.0 },
  { 0.0, 0.0, 0.0, 0.0 },
};

une idée de comment je fais?

le JSON si vous l'écrivez "proprement" ressemble à cela

[
   {
      "type":"schedule",
      "instance":1,
      "property":"weeklySchedule",
      "value":"{{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{06:55:00.00;Boolean:true,18:00:00.00;Null:Null},{06:55:00.00;Boolean:true,17:55:00.00;Null:Null}}"
   }
]

ce qui est dans value n'est pas un JSON cependant donc pour l'analyser vous ne pouvez pas utiliser la bibliothèque ArduinoJson il faut par exemple utiliser sscanf()

une entrée à le format du genre "{07:00:00.00;Boolean:true,18:00:00.00;Null:Null}"
définissez ce que vous voulez extraire exactement

Merci @J-M-L,
donc avec

int h = 0;
int m = 0,
float s = 0.0;
String ed;

sscanf( root_0_value, \"{{%02d:%02d:%04d;Boolean:%04s},  &h, &m, &s, &ed);

avec toutes les donnée que je cherche, je sort mes data c'est ça?

vous voulez la première heure et le booléen ?

"02d:%02d:%04d" ne va pas matcher "07:00:00.00"

vous pourriez utiliser "%d:%d:%d.%d"

Ce que je voudrais c'est écrire dans un tableau "horl1[7][4]" les données de l'horloge hebdomadaire.
Comme j'ai déjà développé une IHM maison en dialogue XML, j'ai changé le server et lui il dialogue en JSON et je ne veux pas tous reprendre :sweat_smile:.
par exemple le premier ensemble {07:00:00.00;Boolean:true,18:00:00.00;Null:Null} représente la plage horaire du lundi.
je voudrai extraire:
07:00:00.00 (reconstruit en seconde) pour l'inscrire dans horl1[0][0]
true (repassé en 1 ou 0 ) pour l'inscrire dans horl1[0][1]
18:00:00.00 (reconstruit en seconde) pour l'inscrire dans horl1[0][2]
Null(repassé en 1 ou 0 ) pour l'inscrire dans horl1[0][3] il peut être aussi en false ou true
et ça répété pour chaque jour de la semaine afin de pouvoir l'affiché sur mon IHM et après la modifier, mais ça c'est après :laughing:

voici un bout de code qui devrait faire l'analyse (tapé ici, non testé)

const char * value = "{{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{06:55:00.00;Boolean:true,18:00:00.00;Null:Null},{06:55:00.00;Boolean:true,17:55:00.00;Null:Null}}";

int parseValue(const char * vPtr) {
  if (vPtr == nullptr || *vPtr != '{') return -1;
  const char * startPtr = vPtr + 1; // on saute la première accolade
  while ( *startPtr == '{') {
    Serial.print("ANALSE DE: ");
    const char * endPtr = strchr(startPtr, '}');
    if (endPtr == nullptr) return -2;
    if (*(endPtr + 1) != ',' && *(endPtr + 1) != '}') return -3;
    Serial.printf("%.*s\n", endPtr - startPtr + 1, startPtr);
    int h, m, s, ms;
    char boolValue;
    int n = sscanf(startPtr+1, "%d:%d:%d.%d;Boolean:%c", &h, &m, &s, &ms, &boolValue);
    if (n != 5) return - 4;
    Serial.print("H:"); Serial.print(h);
    Serial.print(", M:"); Serial.print(m);
    Serial.print(", S:"); Serial.print(s);
    Serial.print(", MS:"); Serial.print(ms);
    Serial.print(", Bool:"); Serial.println(boolValue == 't' ? "VRAI" : "FAUX");

    startPtr = endPtr + 2;
  }
  return 0;
}


void setup() {
  Serial.begin(115200);
  Serial.println(parseValue(value));
}

void loop() {}

il y a quelques vérifications de cohérence mais ce n'est pas 100% blindé, donc vaut mieux passer quelque chose qui ressemble au format attendu :slight_smile:
à vous de stocker dans votre tableau les valeurs extraites au fur et à mesure

1 Like

Merci beaucoup!,
Je vais déjà bien avancé avec ça

@J-M-L Un Grand Merci!!
Ca fonctionne comme je l'imaginais!

parfait

Me revoici ici.
J'ai innocemment modifier le code de @J-M-L de

    int h, m, s, ms;
    char boolValue;
    int n = sscanf(startPtr+1, "%d:%d:%d.%d;Boolean:%c", &h, &m, &s, &ms, &boolValue);
    if (n != 5) return - 4;
    Serial.print("H:"); Serial.print(h);
    Serial.print(", M:"); Serial.print(m);
    Serial.print(", S:"); Serial.print(s);
    Serial.print(", MS:"); Serial.print(ms);
    Serial.print(", Bool:"); Serial.println(boolValue == 't' ? "VRAI" : "FAUX");

à ça

int h, m, s, ms, h1, m1, s1, ms1;
          char boolValue, boolValue1;  //{07:00:00.00;Boolean:true,18:00:00.00;Null:Null}
          int n = sscanf(startPtr + 1, "%d:%d:%d.%d;Boolean:%c,%d:%d:%d.%d;Null:%c", &h, &m, &s, &ms, &boolValue, &h1, &m1, &s1, &ms1, &boolValue1);
          if (n != 5) return -4;
          Serial.print("H:"); Serial.print(h); Serial.print(", M:"); Serial.print(m); Serial.print(", S:"); Serial.print(s); Serial.print(", MS:"); Serial.print(ms); Serial.print(", Bool:"); Serial.println(boolValue == 't' ? "VRAI" : "FAUX");
          Serial.print("H1:"); Serial.print(h1); Serial.print(", M1:"); Serial.print(m1);Serial.print(", S1:"); Serial.print(s1); Serial.print(", MS1:"); Serial.print(ms1); Serial.print(", Bool1:"); Serial.println(boolValue1 == 't' ? "VRAI" : "FAUX");

Afin de sortir toutes les données, mais ça me sort:
ANALYSE DE: {07:00:00.00;Boolean:true,19:10:00.00;Null:Null}

H:7, M:0, S:0, MS:0, Bool:VRAI

H1:-2146586565, M1:1073422416, S1:0, MS1:400, Bool1:FAUX

Je ne comprend pas pourquoi h1, m1, s1 et ms1 sortent comme cela.

Le %c ne correspondi qu’à un seul caractère - ça suffisait pour différencier true de false (le t ou le f) mais ça fait qu’on ne lisait pas plus loin dans la chaîne

Vous avez conservé le if qui teste si seulement 5 paramètres ont été reconnus d’ailleurs donc la fonction dit bien qu’il n’y en a que 5 et que les autres n’ont pas été lus.

Il faut un petit buffer assez grand pour false et un caractère nul et lire avec un %s

Merci @J-M-L pour les conseils !
donc avec

const char * value = "{{07:00:00.00;Boolean:true,19:10:00.00;Null:Null},{04:55:00.00;Boolean:true,18:00:00.00;Null:Null},{08:30:00.00;Boolean:true,20:45:00.00;Null:Null},{01:50:00.00;Boolean:true,15:20:00.00;Null:Null},{10:10:00.00;Boolean:true,22:25:00.00;Null:Null},{03:55:00.00;Boolean:true,18:40:00.00;Null:Null},{03:55:00.00;Boolean:true,18:40:00.00;Null:Null}}"

int parseValue(const char* vPtr) {
        if (vPtr == nullptr || *vPtr != '{') return -1;
        const char* startPtr = vPtr + 1;  // on saute la première accolade
        int x = 0;
        while (*startPtr == '{') {
          Serial.print("ANALYSE DE: ");
          const char* endPtr = strchr(startPtr, '}');
          if (endPtr == nullptr) return -2;
          if (*(endPtr + 1) != '}' && *(endPtr + 1) != ',') return -3; 
          Serial.printf("%.*s\n", endPtr - startPtr + 1, startPtr);
          int h, m, s, ms, h1, m1, s1, ms1;
          char boolValue[6], boolValue1[6];  //{07:00:00.00;Boolean:true,18:00:00.00;Null:Null}
          int n = sscanf(startPtr, "{%d:%d:%d.%d;Boolean:%4s,%d:%d:%d.%d;Null:%4s}", &h, &m, &s, &ms, &boolValue, &h1, &m1, &s1, &ms1, &boolValue1);
          if (n != 10) return -4;
          Serial.print("H:"); Serial.print(h); Serial.print(", M:"); Serial.print(m); Serial.print(", S:"); Serial.print(s); Serial.print(", MS:"); Serial.print(ms); Serial.print(", Bool:"); Serial.println(boolValue );
          Serial.print("H1:"); Serial.print(h1); Serial.print(", M1:"); Serial.print(m1);Serial.print(", S1:"); Serial.print(s1); Serial.print(", MS1:"); Serial.print(ms1); Serial.print(", Bool1:"); Serial.println(boolValue1);
          horl1[x][0] = (h*3600) + (m*60) + s + (ms/1000);
          if (boolValue[0] == 't') horl1[x][1] = 1.00;
          if (boolValue[0] == 'f' || boolValue[0] == 'N') horl1[x][1] = 0;
          horl1[x][2] = (h1*3600) + (m1*60) + s + (ms1/1000);
          if (boolValue1[0] == 't') horl1[x][3] = 1;
          if (boolValue1[0] == 'f' || boolValue1[0] == 'N') horl1[x][3] = 0;
          Serial.print("H:"); Serial.print(horl1[x][0]); Serial.print(", ETAT:");Serial.println(horl1[x][1]);
          Serial.print("H1:"); Serial.print(horl1[x][2]); Serial.print(", ETAT1:");Serial.println(horl1[x][3]);
          x++;
          startPtr = endPtr + 2;
        }
        return 0;
}

void setup() {
  Serial.begin(115200);
  Serial.println(parseValue(value));
}

void loop() {}

je sort

ANALYSE DE: {07:00:00.00;Boolean:true,19:10:00.00;Null:Null}
H:7, M:0, S:0, MS:0, Bool:true
H1:19, M1:10, S1:0, MS1:0, Bool1:Null
H:25200.00, ETAT:1.00
H1:69000.00, ETAT1:0.00
ANALYSE DE: {04:55:00.00;Boolean:true,18:00:00.00;Null:Null}
H:4, M:55, S:0, MS:0, Bool:true
H1:18, M1:0, S1:0, MS1:0, Bool1:Null
H:17700.00, ETAT:1.00
H1:64800.00, ETAT1:0.00
ANALYSE DE: {08:30:00.00;Boolean:true,20:45:00.00;Null:Null}
H:8, M:30, S:0, MS:0, Bool:true
H1:20, M1:45, S1:0, MS1:0, Bool1:Null
H:30600.00, ETAT:1.00
H1:74700.00, ETAT1:0.00
ANALYSE DE: {01:50:00.00;Boolean:true,15:20:00.00;Null:Null}
H:1, M:50, S:0, MS:0, Bool:true
H1:15, M1:20, S1:0, MS1:0, Bool1:Null
H:6600.00, ETAT:1.00
H1:55200.00, ETAT1:0.00
ANALYSE DE: {10:10:00.00;Boolean:true,22:25:00.00;Null:Null}

essayez

const char * value = "{{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{07:00:00.00;Boolean:true,18:00:00.00;Null:Null},{06:55:00.00;Boolean:true,18:00:00.00;Null:Null},{06:55:00.00;Boolean:true,17:55:00.00;Null:Null}}";

int parseValue(const char * vPtr) {
  if (vPtr == nullptr || *vPtr != '{') return -1;
  const char * startPtr = vPtr + 1; // on saute la première accolade
  while ( *startPtr == '{') {
    Serial.print("ANALSE DE: ");
    const char * endPtr = strchr(startPtr, '}');
    if (endPtr == nullptr) return -2;
    if (*(endPtr + 1) != ',' && *(endPtr + 1) != '}') return -3;
    Serial.printf("%.*s\n", endPtr - startPtr + 1, startPtr);
    int h1, m1, s1, ms1;
    int h2, m2, s2, ms2;
    char str1[6], str2[6], str3[6];
    int n = sscanf(startPtr, "{%d:%d:%d.%d;Boolean:%5[^,],%d:%d:%d.%d;%5[^:]:%5[^}]",
                   &h1, &m1, &s1, &ms1, str1, &h2, &m2, &s2, &ms2, str2, str3);
    if (n != 11) {
      return - 4;
    }
    Serial.print("H1:"); Serial.print(h1);
    Serial.print(", M1:"); Serial.print(m1);
    Serial.print(", S1:"); Serial.print(s1);
    Serial.print(", MS1:"); Serial.print(ms1);
    Serial.print(", S1:"); Serial.println(str1);

    Serial.print("H2:"); Serial.print(h2);
    Serial.print(", M2:"); Serial.print(m2);
    Serial.print(", S2:"); Serial.print(s2);
    Serial.print(", MS2:"); Serial.print(ms2);
    Serial.print(", S2:"); Serial.print(str2);
    Serial.print(", S3:"); Serial.println(str3);

    startPtr = endPtr + 2;
  }
  return 0;
}


void setup() {
  Serial.begin(115200);
  Serial.printf("code retour de parseValue : %d\n", parseValue(value));
}

void loop() {}

tapé ici donc sans garantie :slight_smile:

Donc si je comprend bien le faite d'ajouter [^ ] ça ne prend pas en compte si il y a plus ou moins de caractères?
j'ai chercher sur le net sscanf() mais pas trouvé beaucoup d'explication sur son fonctionnement

Le %5[^,] veut dire au plus 5 caractères ou jusqu’à la virgule si elle arrive avant

false fait 5 mais true ne fait que 4 caractères. Ça évite aussi de dépasser la place dispo dans le buffer

Merci pour cette éclaircissement je me coucherais moins bête.
J'ai adapté à mon besoin comme ça :

int h, m, s, ms, h1, m1, s1, ms1;
          char boolValue[6], boolValue1[6], value2[8];  //{07:00:00.00;Boolean:true,18:00:00.00;Null:Null}
          int n = sscanf(startPtr, "{%d:%d:%d.%d;Boolean:%5[^,],%d:%d:%d.%d;%7[^:]:%5[^}]}", &h, &m, &s, &ms, &boolValue, &h1, &m1, &s1, &ms1, &value2, &boolValue1);

par ce que ce coquin de serveur peut me retourné à la place de "Null:Null" "Boolean:false" ou "Boolean:true" dans un "block" journalier.

Encore merci pour l'aide apporté @J-M-L

Ah ok - oui il faut s’adapter
Une fois qu’on a compris scanf() ça va tout seul :wink:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.