Skip to content

Commit

Permalink
Merge pull request #9 from tobozo/1.2.8
Browse files Browse the repository at this point in the history
pure libyaml YAML stream to JSON stream conversion
  • Loading branch information
tobozo authored Oct 22, 2022
2 parents 1271dfe + 8acc9fd commit d1a8ad8
Show file tree
Hide file tree
Showing 6 changed files with 631 additions and 134 deletions.
215 changes: 197 additions & 18 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,25 @@

This arduino library is based on [libyaml](https://github.com/yaml/libyaml).

It provides several ways to convert YAML<=>JSON using libyaml, cJSON or ArduinoJson objects.

Supported platforms (some untested):
### Supported platforms:

- ESP32
- RP2040
- ESP8266
- SAMD

### Features:

- YAML➔JSON and JSON➔YAML conversion
- ArduinoJson serializers/deserializers
- cJSON serializers/deserializers

### Usage

----------------------------


## Usage

```cpp
#include <ArduinoYaml.h>
Expand All @@ -34,29 +41,96 @@ or

```

----------------------------


## Pure libyaml implementation

YAML is a superset of JSON, so native conversion from/to JSON is possible without any additional JSON library.

```cpp
// JSON <=> YAML stream to stream conversion (both ways!), accepts valid JSON or YAML as the input
// Available values for output format:
// YAMLParser::OUTPUT_YAML
// YAMLParser::OUTPUT_JSON
// YAMLParser::OUTPUT_JSON_PRETTY
size_t serializeYml( Stream &source, Stream &destination, OutputFormat_t format );

#### pure libyaml
```
YAML is a superset of JSON, so native conversion from JSON is possible without any additional JSON library.
**Convert YAML to JSON**
```cpp
#include <ArduinoYaml.h>
// JSON stream to YAML stream
size_t serializeYml( Stream &json_src_stream, Stream &yml_dest_stream );
String yaml_str = "hello: world\nboolean: true\nfloat: 1.2345";
StringStream yaml_stream( yaml_str );
serializeYml( yaml_stream, Serial, YAMLParser::OUTPUT_JSON_PRETTY );
```



**Convert JSON to YAML**
```cpp

String json_str = "{\"hello\": \"world\", \"boolean\": true, \"float\":1.2345}";
StringStream json_stream( json_str );

serializeYml( json_stream, Serial, YAMLParser::OUTPUT_YAML );

```
----------------------------
## Bindings
ArduinoJson and cJSON bindings operate differently depending on the platform.
| | ArduinoJson support | cJSON support |
|-----------------|---------------------|------------------------------|
| ESP32 | detected (*) | implicit (built-in esp-idf) |
| ESP8266 | implicit | implicit (bundled) |
| RP2040 | implicit | implicit (bundled) |
| SAMD | implicit | implicit (bundled) |
(*) On ESP32 platform, the detection depends on `__has_include(<ArduinoJson.h>)` macro.
So all ArduinoJson functions will be disabled unless `#include <ArduinoJson.h>` is found **before** `#include <ArduinoYaml.h>`.
On ESP8266/RP2040/SAMD platforms it is assumed that ArduinoJson is already available as a dependency.
In order to save flash space and/or memory, the defaults bindings can be disabled independently by setting one or all of the
following macros before including ArduinoYaml:
```cpp
#define YAML_DISABLE_ARDUINOJSON // disable all ArduinoJson functions
#define YAML_DISABLE_CJSON // disable all cJSON functions
```

Note to self: this should probably be the other way around e.g. explicitely enabled by user.

Note to readers: should ArduinoJson and/or cJSON be implicitely loaded?
[Feedback is welcome!](https://github.com/tobozo/YAMLDuino/issues)


#### ArduinoJson
----------------------------

## ArduinoJson bindings

The support is implicitely enabled on most platforms.


```cpp
#include <ArduinoJson.h> // include this first or functions will be disabled
#include <ArduinoYaml.h>
#include <ArduinoJson.h> // ESP32 plaforms must include this before ArduinoYaml or functions will be disabled
#include <ArduinoYaml.h>
```

Enabling support will expose the following functions:

```cpp
// ArduinoJSON object to YAML string
size_t serializeYml( JsonVariant src_obj, String &dest_string );
// ArduinoJSON object to YAML stream
Expand All @@ -72,17 +146,21 @@ YAML is a superset of JSON, so native conversion from JSON is possible without a

```
----------------------------
## cJSON bindinds
#### cJSON
The support is implicitely enabled on most platforms and will use the bundled cJSON version.
ESP32 will use the built-in version.
⚠️ cJSON has a memory leak with floats, the leak happens only once though, and may be
avoided by quoting the float, which won't affect yaml output.
⚠️ both versions of cJSON have a memory leak with floats, the leak happens only once though, and
may be avoided by quoting the float, which won't affect yaml output.
Enabling support will expose the following functions:
```cpp
// #include <cJSON.h> // no need to include, cJSON is built-in with esp32 and also bundled with ArduinoYaml
#include <ArduinoYaml.h>
// cJSON object to YAML string
size_t serializeYml( cJSON* src_obj, String &dest_string );
Expand All @@ -95,19 +173,120 @@ avoided by quoting the float, which won't affect yaml output.
```

----------------------------

## String/Stream helper

Although `const char*` is an acceptable source type for conversion, using `Stream` is recommended as it is more memory efficient.

The `StringStream` class is provided with this library as a helper.

```cpp

String my_json = "{\"blah\":true}";

StringStream json_input_stream(my_json);

String my_output;
StringStream output_stream(my_output);

```
The `StringStream` bundled class is based on Arduino `String` and can easily be replaced by any class inheriting from `Stream`.
```cpp
class StringStream : public Stream
{
public:
StringStream(String &s) : str(s), pos(0) {}
virtual ~StringStream() {};
virtual int available() { return str.length() - pos; }
virtual int read() { return pos<str.length() ? str[pos++] : -1; }
virtual int peek() { return pos<str.length() ? str[pos] : -1; }
virtual size_t write(uint8_t c) { str += (char)c; return 1; }
virtual void flush() {}
private:
String &str;
unsigned int pos;
};
```

See [ArduinoStreamUtils](https://github.com/bblanchon/ArduinoStreamUtils) for other types of streams (i.e. buffered).


----------------------------


## Output decorators


JSON and YAML indentation levels can be customized:


```cpp
void YAML::setYAMLIndent( int spaces_per_indent=2 ); // min=2, max=16
void YAML::setJSONIndent( const char* spaces_or_tabs=JSON_SCALAR_TAB, int folding_depth=JSON_FOLDING_DEPTH );

```
Set custom JSON indentation and folding depth:
```cpp
// two spaces per indentation level, unfold up to 8 nesting levels
YAMLParser::setJSONIndent(" ", 8 ); // lame fact: folds on objects, not on arrays
```


Set custom YAML indentation (minimum=2, max=16):

```cpp
// annoy your friends with 3 spaces indentation, totally valid in YAML
YAML::setYAMLIndent( 3 );

```
----------------------------
## Debug
The debug level can be changed at runtime:
```cpp
void YAML::setLogLevel( LogLevel_t level );
```

Set library debug level:

```cpp
//
// Accepted values:
// LogLevelNone : No logging
// LogLevelError : Errors
// LogLevelWarning : Errors+Warnings
// LogLevelInfo : Errors+Warnings+Info
// LogLevelDebug : Errors+Warnings+Info+Debug
// LogLevelVerbose : Errors+Warnings+Info+Debug+Verbose
YAMLParser::setLogLevel( YAML::LogLevelDebug );
```
----------------------------
### Credits and special thanks to:
## Credits and special thanks to:
- [@yaml](https://github.com/yaml)
- [@DaveGamble](https://github.com/DaveGamble)
- [@bblanchon](https://github.com/bblanchon)
- [@vikman90](https://github.com/vikman90/yaml2json)
### Additional resources:
## Additional resources:
- ArduinoJson : https://github.com/bblanchon/ArduinoJson
- ArduinoStreamUtils : https://github.com/bblanchon/ArduinoStreamUtils
- cJSON : https://github.com/DaveGamble/cJSON
- libyaml : https://github.com/yaml/libyaml
Loading

0 comments on commit d1a8ad8

Please sign in to comment.