squix78 / json-streaming-parser

Arduino library for parsing potentially huge json streams on devices with scarce memory
MIT License
205 stars 88 forks source link

Examples? #14

Open anthonyrubalcaba opened 6 years ago

anthonyrubalcaba commented 6 years ago

What examples? I read through the 3 files in the examples folder but I don't see any examples of getting values from the parsed json.

Leonos commented 5 years ago

I am afraid I must agree. The example JsonStreamingParser.ino doesn't bring me anywhere. Daniel spends so much time creating and promoting it. I don't understand that he then makes it so hard for others to use the parser. Unfortunately, the link to the tell-all does not exist anymore... (from https://blog.squix.org/2017/01/esp8266-the-json-streaming-parser.html):

If this example was too simple then have a look here: https://github.com/squix78/esp8266-weather-station/blob/master/WundergroundClient.cpp This is the code which parses the responses from Wunderground for my WeatherStation.

Or maybe it's just targeted at people more intelligent than me. :)

JoeWiseman commented 5 years ago

Hi there,

I'm not an expert in programming and quite new to "Adruinos"... So it might be my fault. But I have to agree to the two previous speaker ...

I'm trying to parse an 5-day-request from openweathermap.org, which seem to be too long for the ArduinoJSON-lib :-(, which I got to work for a one-day-weather-request after searching a while ....

As mentioned above the example-directory does not lead me anywhere but into depression ;-)

It would be great to get some simple, concret examples how to use the lib in my own code. forecast.json.txt forecast.txt

I put the JSON (renamed beause of uploading) output and the TXT output as an attechment.

What I need from the whole anser is just the "main"/"temp" and the "dt_txt" from the first 6 entries of the "list": root/list[0]/main/temp (as float) & root/list[0]/dt_txt (as string) root/list[1]/main/temp (as float) & root/list[1]/dt_txt (as string) .... root/list[6]/main/temp (as float) & root/list[6]/dt_txt (as string)

would be great to get the code.... I think that this would also help other one to accept you lib as a friend not as a time-crunching monster :-D

Best regards Joe

Bodmer commented 5 years ago

I had the same trouble figuring it all out, this library and the test (text output) example may help.

At the moment I am migrating the library to this fork in the hope it consumes less memory.

Leonos commented 5 years ago

@Bodmer Thank you very much for that, much appreciated. Will study it and see if it makes things clearer for me.

squix78 commented 5 years ago

Hi guys I'm sorry that you are heaving issues with my parser library. I am aware that the examples are not the best but I thought that writing a blog post about it might shed some lights on it: https://blog.squix.org/2017/01/esp8266-the-json-streaming-parser.html

Also since I am using this library a lot you might get information from other code that I wrote with this library: https://github.com/ThingPulse/esp8266-weather-station/tree/master/src

The basic idea is that you have to keep track of the current context by yourself. So for your samples root/list[0]/main/temp (as float) root/list[0]/dt_txt (as string) root/list[1]/main/temp (as float) root/list[1]/dt_txt (as string) I would write a function like this:

void YourParser::value(String value) {
   if (currentKey == "temp" && listIndex == 0) {
      this->temp1 = value;
   }
   if (currentKey == "temp" && listIndex == 1) {
      this->temp2 = value;
   }
  if (currentKey == "dt_txt") {
      ....
      listIndex++; // Increase listIndex, assuming that dt_txt shows up after temp
  }
}

The problem with writing good samples is that the implementation highly depends on your goal and the structure of the json object. If a key only shows up in the whole JSON structure it is very easy to get the value. But if a key is used in several different objects you have to write your parser with context awareness: where am I in the whole document.

Bodmer commented 5 years ago

Hi Daniel, firstly - thanks for writing this library, it works really well. I started looking at the ArduinoJSON library but could not figure out how to stream serially through it, the online tool creates code for you but needed a 55kbyte buffer! This seemed daft when the entire JSON message is only 28kbytes.

I thought I has a memory resource issue with spurious crashes using your library so adapted my code for altrunners fork. It turned out to be a bug in my own code though, so I wasted my time there, the error reporting during decoding in that fork proved useful.

The blog is good but I got the same from Google and had a bit of a jargon blockage in getting to understand it all and how the information related to the way the library works. It was fun figuring it out bit by bit (pun!) by analyzing implementation examples though. There is a knowledge bridge that has to be built across the large gap between the simple example and a full blown library.

I understand this is your free time spent on this so thanks again.

Bodmer commented 5 years ago

I have added a single sketch example to my fork that, I think, bridges the complexity gap between the simple existing example and the Weather Station library. You can find it here. It connects to a website to fetch geographically near passes of the International Space Station and sends the parsed data to the serial port. I have added lots of comments to help understand what the different sections of code do, the example will need to be adapted slightly to work with Daniel's library but the principles are the same.

Bodmer commented 5 years ago

I have created a pull request for the example, adapted to make it compatible with this repository.

Leonos commented 5 years ago

@squix78 @Bodmer I would like to thank you both for your efforts to make this understandable and available. I do understand that examples are often based on existing pieces of code. For the 'learner' (me ;)) it is then sometimes difficult to see what is part of the functionality I would like to learn and what is part of the rest. Normally I do not look inside .h and .cpp library files very often, I just use them after studying the examples. But here, with parsing json, it seems you have to create your own .h/.cpp files. And although also just c++, those use a particular syntax I am not yet very comfortable with. In the mean time, you made a lot of information available. If I understand it correctly, we now have squix78's json-streaming-parser, Bodmer's json-streaming-parser, Bodmer's JSON_Decoder and then there's altrunners' json-streaming-parser that gets updated with Bodmer's code, I am still in doubt whether all these choices are a good thing or not, in my situation. :) I will need some more time to investigate all this and then make a decision what's best for me, I guess. In any case, thanks again for your time and work done.

Bodmer commented 5 years ago

@Leonos I would stick with Daniel's library here as that is the one that the Arduino IDE calls up and I went down the path if creating a fork based on mistakes I made. Once I fixed the bug in my code I found Daniel's library worked perfectly. I agree forks add to the bewilderment, there is no advantage to you in using my fork, but it did aid me in the learning process.

The need for creating .h and .cpp files in your sketch comes from the necessity of the json streaming parser library to call back to different functions in your own code as the JSON is decoded, this can only be done by making a C++ class and providing the parser library with a single pointer to that class. The parser then can call your functions such as value() at the approprite time.

If you are decoding small JSON messages the the Arduino JSON library may make things easier as it has a web page that generates code for you.

Leonos commented 5 years ago

@Bodmer Thanks again for your time answering and explanation. I now do see why I will have to dive into those .h and .cpp files, there's no other way.

As so many people, I have to find an alternative for Weather Underground's API. I use current conditions, forecast and 'astronomy' in a clock I made and at the time I did the parsing myself (or actually, I wrote code that allowed the ESP8266 do the parsing for me ;)).

I have looked at many alternatives, but the only one that gives the best results, compared to WU and my own observations, for a particular location in Spain, is Apixu. I thought I would save time by using an existing json parser instead of doing my own - basic and not very flexible - parsing. For example, my code can't handle any json that doesn't have a '\n' at the end of every line.

I am not so sure about the time saving now, haha. I would have loved to use OpenWeatherMap as I feel it is the most future-proof - free and available 'forever'. But like I said, the weather is off, a lot. It gets its weather from Valencia, 100 km away. In fact it says it is raining now while it is actually splendid weather and rain is expected only after 21:00h tonight with just < 25% chance.

Your ISS example is really great, surely an excellent way to get up and running. I think in the end I will be able to write a parser for Apixu. I've indeed tried the Arduino JSON library but the files are too big for it to handle.

Thanks for recommending Daniel's code over the alternatives but what exactly is the difference between the json-streaming-parser and your JSON_Decoder? I can't find it anymore, but I thought I'd read that your or altrunner's version was more efficient in memory?

Bodmer commented 5 years ago

@Leonos You may find the APIXU library I created and uploaded here of interest.

The JSON_Decode library has differences to the original as detailed in the ReadMe.

Leonos commented 5 years ago

Wow, @Bodmer, what an incredible service! Thank you very, very much!

Yes, that Readme... I knew I'd read somewhere that there was a benefit in altrunners' code but couldn't find where anymore. Altrunner's Readme is just Daniel's Readme, as if there were no changes. But it was in your Readme where you explain the String versus char change. Anyway, thanks again for your support.

ZioGuido commented 5 years ago

In case someone is interested, here's a link to a repository of one of my projects that uses this library to parse the entire 5-day weather forecast feed from OWM: https://github.com/ZioGuido/HomeAutomationRemote

The JSON received from OWM is > 24 Kb large and couldn't be parsed with ArduinoJson, so I used this streaming library and implemented my own listener to catch just the data I needed. Hope it helps.

You might want to extract the interesting part and make it an example to add to this library.