JSON Objekt Feld erzeugen und auswerten

Gast #5728107
Lesenswert?

Hallo,

leider ist für mich C++ böhmische Dörfer und die Denkweise hinter der 
JSON API noch nicht ganz klar. Ich möchte einfach nur einen Satz von 10 
Wetterberichten, der sich bereits im JSON Buffer befindet als Feld 
auswerten.

Bisher habe ich mir nur das zusammen gesucht, was auch klappt:

Das Parsen... ich hole 10 Datensätze von der OpenweatherMap, d.h. 10*3 
Stunde = 30 Stunde Vorhersagen
1
const size_t capacity = JSON_ARRAY_SIZE(3) + 2*JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + 3*JSON_OBJECT_SIZE(4) +JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(6) + JSON_OBJECT_SIZE(12) + 480;
2

3
DynamicJsonBuffer jsonBuffer(10 * capacity);
4
JsonObject& root = jsonBuffer.parseObject(client);

Wurzel der Liste festlegen:
JsonArray& list = root["list"];

/* 2 Sätze auslesen: now und later */
1
JsonObject& now = list[0];
2
JsonObject& later = list[1];
3

4
PressureNow        = now["main"]["pressure"];
5
TempNow         = now["main"]["temp"];
6
WSpeedNow        = now["wind"]["speed"];
usw.

Was nicht klappt ist ein Feld an zu legen, wo ich zb 10 Sätze 
hineinschreibe :-(  Mit now und later habe ich zwei aber ich will das in 
einem Array haben. also zb feld[n]

JsonObject& feld[10];    <- Compiler Mecker: declaration of feld as 
array of referces.

for (int i = 0; i < 10; i++) {
Auswertung.....
}

Kann da mal jemand helfen? Möglichst mit Code?
Gast #5728153
Lesenswert?

das ist eines mit 2 Datensätzen, ich kann aber auch 10 abrufen. Und 
genau das will ich jetzt tun. Natürlich erzeuge ich nicht 10 Variablen 
now,later,nochlater,viellater etc. sondern will die 10 Sätze einfach nur 
auslesen und in meine eigenen Vars packen, damit ich auf vertrauten 
Boden komme und weiterverarbeiten kann.
1
JsonArray& list = root["list"];
2
    
3
JsonObject& now = list[0];
4
JsonObject& later = list[1];
5

6
  /* Aktuellen Druck und Temperatur holen */
7
  debug(F("Hole JSON Buffer Daten..."));
8
  /* Aktuelle Daten */
9
  PressureNow        = now["main"]["pressure"];
10
  TempNow         = now["main"]["temp"];      /* Temperatur */
11
  WSpeedNow        = now["wind"]["speed"];
12
  WeatherIDNow      = now["weather"][0]["id"];
13
  CloudsAllNow      = now["clouds"]["all"];
14
  String Date       = now["dt_txt"];
15
  String TextNow       = now["weather"][0]["description"];
16
  /* Vorhersage */
17
  String TextLater     = later["weather"][0]["description"];
18
  CloudsAllLater      = later["clouds"]["all"];
19
  TempLater         = later["main"]["temp"];      /* Temperatur */
1
{
2
  "cod": "200",
3
  "message": 0.0023,
4
  "cnt": 2,
5
  "list": [
6
     {
7
      "dt": 1547726400,
8
      "main": {
9
        "temp": 5.86,
10
        "temp_min": 3.93,
11
        "temp_max": 5.86,
12
        "pressure": 998.26,
13
        "sea_level": 1012.84,
14
        "grnd_level": 998.26,
15
        "humidity": 98,
16
        "temp_kf": 1.93
17
      },
18
      "weather": [
19
        {
20
          "id": 500,
21
          "main": "Rain",
22
          "description": "light rain",
23
          "icon": "10d"
24
        }
25
      ],
26
      "clouds": {
27
        "all": 44
28
      },
29
      "wind": {
30
        "speed": 6.17,
31
        "deg": 241.002
32
      },
33
      "rain": {
34
        "3h": 0.0825
35
      },
36
      "sys": {
37
        "pod": "d"
38
      },
39
      "dt_txt": "2019-01-17 12:00:00"
40
    },
41
 
42
  {
43
      "dt": 1547737200,
44
      "main": {
45
        "temp": 4,
46
        "temp_min": 2.55,
47
        "temp_max": 4,
48
        "pressure": 997.53,
49
        "sea_level": 1012.32,
50
        "grnd_level": 997.53,
51
        "humidity": 100,
52
        "temp_kf": 1.45
53
      },
54
      "weather": [
55
        {
56
          "id": 500,
57
          "main": "Rain",
58
          "description": "light rain",
59
          "icon": "10d"
60
        }
61
      ],
62
      "clouds": {
63
        "all": 92
64
      },
65
      "wind": {
66
        "speed": 4.98,
67
        "deg": 259.003
68
      },
69
      "rain": {
70
        "3h": 1.8475
71
      },
72
      "snow": {
73
        "3h": 0.006
74
      },
75
      "sys": {
76
        "pod": "d"
77
      },
78
      "dt_txt": "2019-01-17 15:00:00"
79
    }
80
  ],
81
  "city": {
82
    "id": 2952444,
83
    "name": "Barntrup",
84
    "coord": {
85
      "lat": 51.991,
86
      "lon": 9.1128
87
    },
88
    "country": "DE",
89
    "population": 9513
90
  }
91
}
Gast #5728167
Lesenswert?

JsonObject& now = list[0];
JsonObject& later = list[1];

Damit habe ich schon die Infos, die ich brauche für die ersten beiden 
Sätze, die 3h auseinander liegen. 0 für jetzt und 1 für in 3 Stunden. 
Und nun nur noch das ganze erweitern auf 10 Sätze. Aber JsonObject& mit 
dem & hinter dem Typ ist mir aus C nicht bekannt, das scheint eine 
Instanz eines Objektes zu sein. Now wird zum Zeiger auf den Inhalt bzw 
die Methoden dieser Klasse. So mein rudimentäres Verständnis von c++....

Und da soll es alles rein:
1
/* Wetter Datensatz */
2
typedef struct {
3
    int      FC_Hours;        /* Stunden in Zukunft: 0,3,6,9,12,15,.... */
4
    int     wid;          /* Die ID der aktuellen Wetterlage */  
5
    int     Pressure;        /* Druck */
6
    double     Temp;          /* Temperatur */
7
    double    WSpeed;          /* Windgeschwindigkeit */
8
    int     CloudsAll;        /* Bewölkung in % */
9
    String    DateStamp;        /* Zeitstempel als String */ 
10
    String    WetterText;        /* Wetter als Satz */
11
} wetter_t;
12

13
wetter_t wetter[10] = {0,};
Angehängte Dateien:
Persönliche Seite #5728374
Lesenswert?

Christian J. schrieb:
> sondern will die 10 Sätze einfach nur auslesen und in meine eigenen Vars
> packen,

Ich würde hier anstelle von
1
   PressureNow =  now["main"]["pressure"];

etwas à la
1
   PressureNow =  List[0]["main"]["pressure"];

ausprobieren.

Und stattt "PressureNow" ein Array von Drücken:
1
for (i = 0; i < Anzahl; i++)
2
{
3
  Pressure[i] = List[i]["main"]["pressure"];
4
}

bzw. sehen, ob es einen tauglichen Listeniterator gibt und den dann 
verwenden.

Oder hab' ich das Problem jetzt komplett missverstanden?
Gast #5728462
Lesenswert?

Rufus Τ. F. schrieb:
> Oder hab' ich das Problem jetzt komplett missverstanden?

Nee, ich denke schon richtig. Das problem vieler Anleitungen wie auch 
bei dieser ist, dass sie von leuten geschrieben werden, die so tief in 
der Materie stecken, dass sie die Fragen eines Neulings nicht 
"verstehen". Im Grund ist diese nur, wie die Daten in dem Container 
abgelegt sind (nach dem Parsen) und wie der Zugriff erfolgt. Json an 
sich ist nix Besonders, ein Datenformat wie xml, lesbar von Menschen und 
Maschinen zur strukturierten Ablage von Daten, die eine hierarische 
Ordnung haben können.  Ihc probiers mal heute abend aus, wenn ich Zeit 
habe...
Gast #5728466
Lesenswert?

Weisst du zufällig was diese 0 da bedeutet?
WeatherIDNow      = now["weather"][0]["id"];
Ist auch nur abgeschrieben.....

PS: Deine Lösung kompiliert schonmal durch.... das gibt Hoffung.

PSS: Und sie funktioniert auch :-)))) Klasse, danke Meister!
Gast #5728979
Lesenswert?

Ah ok. Es reicht wennn man das versteht, was man grad braucht denke ich. 
Bin ja kein Entwickler für solche Anwendungen.

Und warum muss ich solche Verrenkungen machen über die foo Variablen? 
Direkte Zuweisung auf den gleichen Typ (global) geht nicht. Da wird 
gemeckert. Es können auch keine rechnungen gemacht werden. Die Ausdrücke 
müssen so da stehen wie sie sind. Also die *3.6 kann nicht geklammert 
werden.
1
  for (int i = 0; i < (HFcN-1);i++) {
2
    wetter[i].wid     =  list[i]["weather"][0]["id"];
3
    wetter[i].Pressure  = list[0]["main"]["pressure"];
4
    wetter[i].Temp     = list[0]["main"]["temp"];
5
    wetter[i].WSpeed   =  list[0]["wind"]["speed"];
6
    wetter[i].WSpeed   *= 3.6;
7
    wetter[i].CloudsAll = list[i]["clouds"]["all"];
8
    String foo1         = list[i]["dt_txt"];
9
    wetter[i].DateStamp = foo1;
10
    String foo2      = list[0]["weather"][0]["description"];
11
    wetter[i].WetterText = foo2;
12
  }
Gast #5728993
Lesenswert?

Rufus Τ. F. schrieb:
> Aha. Der Compiler gibt eine Meldung "Gemecker" aus, oder wie muss man
> sich das vorstellen?

Es ist ein ganzer Wust, der sich nicht auf die Zeile bezieht, sondern 
aus den Quelltext der Json Lib. U.a. dass keine passende Methode 
gefunden wurde. Nur der Typ String macht diese probleme, die anderen 
nicht.
Gast #5728994
Lesenswert?

Ich habe mal etwas gekürzt :-)

Arduino: 1.8.5 (Windows 7), Board: "NodeMCU 1.0 (ESP-12E Module), 80 
MHz, Flash, 4M (1M SPIFFS), v2 Lower Memory, Disabled, None, Only 
Sketch, 256000"

Build-Optionen wurden verändert, alles wird neu kompiliert
K:\ESP8266\WetterOled\tools.ino: In function 'int GetWeatherData()':

tools:186: error: ambiguous overload for 'operator=' (operand types are 
'String' and 'ArduinoJson::Internals::EnableIf<true, 
ArduinoJson::Internals::JsonObjectSubscript<const char*> >::type {aka 
ArduinoJson::Internals::JsonObjectSubscript<const char*>}')

   wetter[i].DateStamp        =  list[i]["dt_txt"];

exit status 1
ambiguous overload for 'operator=' (operand types are 'String' and 
'ArduinoJson::Internals::EnableIf<true, 
ArduinoJson::Internals::JsonObjectSubscript<const char*> >::type {aka 
ArduinoJson::Internals::JsonObjectSubscript<const char*>}')

Dieser Bericht wäre detaillierter, wenn die Option
"Ausführliche Ausgabe während der Kompilierung"
in Datei -> Voreinstellungen aktiviert wäre.
Gast #5729070
Lesenswert?

Rufus Τ. F. schrieb:

> Was passiert dann?

K:\ESP8266\WetterOled\tools.ino: In function 'int GetWeatherData()':

tools:186: error: call of overloaded 
'String(ArduinoJson::Internals::EnableIf<true, 
ArduinoJson::Internals::JsonObjectSubscript<const char*> >::type)' is 
ambiguous

   wetter[i].DateStamp  =  (String)list[i]["dt_txt"];

Das Problem bezieht sich nur auf die String Klasse, die ja ohnehin mit 
Vorsicht zu genießen ist und auf "double".

Nur das ist kompilierbar und liefert das richtige Eregbnis:
String foo1         =  list[i]["dt_txt"];
wetter[i].DateStamp =  foo1;

Das hier aber läuft durch. Ohne den Cast aber nicht.
wetter[i].WSpeed   =  3.6 * (double)list[i]["wind"]["speed"];

ich hoffe doch, dass die Json Klasse einen Destruktor hat, der den 
dynamischen Speicher wieder frei gibt, wenn die Routine verlassen wird. 
Due legt das nämlich auf dem Heap an wie ich meine und nicht auf dem 
Stack.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren