forked from bblanchon/ArduinoJson
Compare commits
146 Commits
Author | SHA1 | Date | |
---|---|---|---|
4f56afe89e | |||
339de21f1c | |||
25c428c1e9 | |||
0045bb3e35 | |||
4e61a839a5 | |||
a48fbac7d7 | |||
af7dd55d34 | |||
525649c416 | |||
1f86016320 | |||
c38af3e32c | |||
0a0757945e | |||
e63cde3922 | |||
5bb6cd0fa9 | |||
bbc18b5ca4 | |||
6d3b70f4a3 | |||
cbedcdf93b | |||
6fcf9edf9a | |||
bb11fcba89 | |||
a87b2bf5bf | |||
f28997e367 | |||
42968be535 | |||
6c1ab912ff | |||
99521cc718 | |||
b3613f7137 | |||
1b62502b36 | |||
adb8fa4d44 | |||
3b6ce65054 | |||
be6c4bf4d1 | |||
4e6ad31d6a | |||
1cec019457 | |||
2e97dbdedc | |||
8f9d3b638f | |||
8be590e591 | |||
8baf21b6e8 | |||
935cb068ab | |||
efd8c0ff5c | |||
757c86ddc5 | |||
0efe8bc74a | |||
65d03c9001 | |||
df2e640b16 | |||
895482de15 | |||
477c9c2c6e | |||
50b2a1b4a7 | |||
78a920a5fc | |||
bae5c36f41 | |||
538b15b400 | |||
daba65d987 | |||
5b1c2047a4 | |||
81c7b9f700 | |||
2222714d68 | |||
dd5cf661e3 | |||
b560a87e15 | |||
4d4d775e7a | |||
9bcb5610e8 | |||
cb0973ab38 | |||
c7fb77203b | |||
e87bde6594 | |||
922b131f8d | |||
ae73a06328 | |||
61e53a505d | |||
937837848c | |||
1fba9767d3 | |||
621068260d | |||
e8831c28d9 | |||
a9b8e280fe | |||
4d5a7114c1 | |||
c3359d3eb9 | |||
c84860e3f4 | |||
1401665129 | |||
19e007c3f5 | |||
88f630cee5 | |||
a57220debc | |||
69d682ce81 | |||
81f7849c26 | |||
10068e7b22 | |||
5b2ee9ed29 | |||
93ddb9498e | |||
495efd8629 | |||
f548093d86 | |||
5f77949636 | |||
e26cea59e5 | |||
1800a8e89e | |||
1d064d709b | |||
b7933f85ba | |||
0240270492 | |||
dd8baea373 | |||
568b8988d8 | |||
4f4b35bd41 | |||
ff4060f5d1 | |||
ebb257df6e | |||
48a91a219c | |||
e75e3b6527 | |||
63ae9ef096 | |||
33508e3fe0 | |||
1c4d4bfd2d | |||
18587d132b | |||
d12e25bd8a | |||
25118ad8c0 | |||
7ab728e996 | |||
ca99749f28 | |||
55487ad668 | |||
6ea9574330 | |||
1e44f5522e | |||
786fe994aa | |||
6b61617133 | |||
45dfdbd5e4 | |||
dd6fd6f198 | |||
ca53abdc41 | |||
5e4c4a4bdc | |||
aa6cf308db | |||
b8df795cb5 | |||
4c387e9062 | |||
d57234e92c | |||
6f247a5080 | |||
d306422ed9 | |||
2a20c5a25c | |||
1118dd7b53 | |||
3d4f0f741d | |||
77a3e1737d | |||
a27bb3097a | |||
5c119099f3 | |||
bb705bab63 | |||
22ca52326c | |||
aa8cff7101 | |||
df25a21050 | |||
f18f554c2f | |||
c8c1add4ab | |||
3d8b31b1ec | |||
80e0a51c15 | |||
dd416e51f3 | |||
7059e35938 | |||
17d1f5cd2f | |||
8c2a1fab72 | |||
c844db8659 | |||
3661f801a5 | |||
a35d503a02 | |||
2ed6317135 | |||
a278cd825f | |||
0eaa5e3f1b | |||
b35095ded1 | |||
597b4c7888 | |||
995aa7dd40 | |||
a58fb13d37 | |||
d994178678 | |||
dc1b3f3d78 | |||
006fc13141 |
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
*.sdf
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
Debug
|
||||||
|
ipch
|
||||||
|
*.opensdf
|
28
ArduinoJson.sln
Normal file
28
ArduinoJson.sln
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 2013
|
||||||
|
VisualStudioVersion = 12.0.21005.1
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JsonGeneratorTests", "JsonGeneratorTests\JsonGeneratorTests.vcxproj", "{B9545D97-E084-4A19-8E48-929157064360}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JsonParserTests", "JsonParserTests\JsonParserTests.vcxproj", "{4DD596EF-0185-4AB4-A3C2-F20C496F7806}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{B9545D97-E084-4A19-8E48-929157064360}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{B9545D97-E084-4A19-8E48-929157064360}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{B9545D97-E084-4A19-8E48-929157064360}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{B9545D97-E084-4A19-8E48-929157064360}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{4DD596EF-0185-4AB4-A3C2-F20C496F7806}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{4DD596EF-0185-4AB4-A3C2-F20C496F7806}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{4DD596EF-0185-4AB4-A3C2-F20C496F7806}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{4DD596EF-0185-4AB4-A3C2-F20C496F7806}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
28
CHANGELOG.md
Normal file
28
CHANGELOG.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
Arduino JSON library: change log
|
||||||
|
================================
|
||||||
|
|
||||||
|
v2.0
|
||||||
|
----
|
||||||
|
|
||||||
|
* Added JSON encoding.
|
||||||
|
* Renamed the library `ArduinoJsonParser` becomes `ArduinoJson`
|
||||||
|
|
||||||
|
**Breaking change**: you need to add the following line at the top of your program.
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Parser;
|
||||||
|
|
||||||
|
v1.2
|
||||||
|
----
|
||||||
|
|
||||||
|
* Example: changed `char[] json` into `char json[]`. Damn it C# !
|
||||||
|
|
||||||
|
v1.1
|
||||||
|
----
|
||||||
|
|
||||||
|
* Example: changed `char* json` into `char[] json` so that the bytes are not write protected
|
||||||
|
* Fixed parsing bug when the JSON contains multi-dimensional arrays
|
||||||
|
|
||||||
|
v1.0
|
||||||
|
----
|
||||||
|
|
||||||
|
Initial release
|
42
JsonArray.h
42
JsonArray.h
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* malloc-free JSON parser for Arduino
|
|
||||||
* Benoit Blanchon 2014 - MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __JSONARRAY_H
|
|
||||||
#define __JSONARRAY_H
|
|
||||||
|
|
||||||
#include "JsonObjectBase.h"
|
|
||||||
|
|
||||||
class JsonHashTable;
|
|
||||||
|
|
||||||
class JsonArray : public JsonObjectBase
|
|
||||||
{
|
|
||||||
template <int N>
|
|
||||||
friend class JsonParser;
|
|
||||||
|
|
||||||
friend class JsonHashTable;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
JsonArray() {}
|
|
||||||
|
|
||||||
int getLength()
|
|
||||||
{
|
|
||||||
return tokens != 0 ? tokens[0].size : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonArray getArray(int index);
|
|
||||||
bool getBool(int index);
|
|
||||||
double getDouble(int index);
|
|
||||||
JsonHashTable getHashTable(int index);
|
|
||||||
long getLong(int index);
|
|
||||||
char* getString(int index);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
JsonArray(char* json, jsmntok_t* tokens);
|
|
||||||
jsmntok_t* getToken(int index);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
12
JsonGenerator.cpp
Normal file
12
JsonGenerator.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* malloc-free JSON parser for Arduino
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This file is here to help the Arduino IDE find the .cpp files
|
||||||
|
|
||||||
|
#include "JsonGenerator/EscapedString.cpp"
|
||||||
|
#include "JsonGenerator/JsonArrayBase.cpp"
|
||||||
|
#include "JsonGenerator/JsonValue.cpp"
|
||||||
|
#include "JsonGenerator/JsonHashTableBase.cpp"
|
||||||
|
#include "JsonGenerator/StringBuilder.cpp"
|
7
JsonGenerator.h
Normal file
7
JsonGenerator.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* malloc-free JSON parser for Arduino
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "JsonGenerator/JsonArray.h"
|
||||||
|
#include "JsonGenerator/JsonHashTable.h"
|
47
JsonGenerator/EscapedString.cpp
Normal file
47
JsonGenerator/EscapedString.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "EscapedString.h"
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Internals;
|
||||||
|
|
||||||
|
static inline char getSpecialChar(char c)
|
||||||
|
{
|
||||||
|
// Optimized for code size on a 8-bit AVR
|
||||||
|
|
||||||
|
const char* p = "\"\"\\\\\bb\ff\nn\rr\tt\0";
|
||||||
|
|
||||||
|
while (p[0] && p[0] != c)
|
||||||
|
{
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t printCharTo(char c, Print& p)
|
||||||
|
{
|
||||||
|
char specialChar = getSpecialChar(c);
|
||||||
|
|
||||||
|
return specialChar != 0
|
||||||
|
? p.write('\\') + p.write(specialChar)
|
||||||
|
: p.write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t EscapedString::printTo(Print& p) const
|
||||||
|
{
|
||||||
|
const char* s = rawString;
|
||||||
|
|
||||||
|
if (!s) return p.print("null");
|
||||||
|
|
||||||
|
size_t n = p.write('\"');
|
||||||
|
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
n += printCharTo(*s++, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n + p.write('\"');
|
||||||
|
}
|
29
JsonGenerator/EscapedString.h
Normal file
29
JsonGenerator/EscapedString.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Internals
|
||||||
|
{
|
||||||
|
class EscapedString
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void set(const char* s)
|
||||||
|
{
|
||||||
|
rawString = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t printTo(Print&) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* rawString;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
28
JsonGenerator/JsonArray.h
Normal file
28
JsonGenerator/JsonArray.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonArrayBase.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Generator
|
||||||
|
{
|
||||||
|
template<int N>
|
||||||
|
class JsonArray : public JsonArrayBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JsonArray()
|
||||||
|
: JsonArrayBase(items, N)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Internals::JsonValue items[N];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
34
JsonGenerator/JsonArrayBase.cpp
Normal file
34
JsonGenerator/JsonArrayBase.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "JsonArrayBase.h"
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Generator;
|
||||||
|
using namespace ArduinoJson::Internals;
|
||||||
|
|
||||||
|
size_t JsonArrayBase::printTo(Print& p) const
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
n += p.write('[');
|
||||||
|
|
||||||
|
// NB: the code has been optimized for a small size on a 8-bit AVR
|
||||||
|
|
||||||
|
const JsonValue* current = items;
|
||||||
|
for (int i = count; i > 0; i--)
|
||||||
|
{
|
||||||
|
n += current->printTo(p);
|
||||||
|
current++;
|
||||||
|
|
||||||
|
if (i > 1)
|
||||||
|
{
|
||||||
|
n += p.write(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n += p.write(']');
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
49
JsonGenerator/JsonArrayBase.h
Normal file
49
JsonGenerator/JsonArrayBase.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonObjectBase.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Generator
|
||||||
|
{
|
||||||
|
class JsonArrayBase : public JsonObjectBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JsonArrayBase(Internals::JsonValue* items, int capacity)
|
||||||
|
: items(items), capacity(capacity), count(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void add(T value)
|
||||||
|
{
|
||||||
|
if (count >= capacity) return;
|
||||||
|
|
||||||
|
items[count++].set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int DIGITS>
|
||||||
|
void add(double value)
|
||||||
|
{
|
||||||
|
if (count >= capacity) return;
|
||||||
|
|
||||||
|
Internals::JsonValue& v = items[count++];
|
||||||
|
v.set<DIGITS>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t printTo(Print& p) const;
|
||||||
|
|
||||||
|
using JsonObjectBase::printTo;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Internals::JsonValue* items;
|
||||||
|
int count, capacity;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
27
JsonGenerator/JsonHashTable.h
Normal file
27
JsonGenerator/JsonHashTable.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonHashTableBase.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Generator
|
||||||
|
{
|
||||||
|
template<int N>
|
||||||
|
class JsonHashTable : public JsonHashTableBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JsonHashTable()
|
||||||
|
: JsonHashTableBase(items, N)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
KeyValuePair items[N];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
36
JsonGenerator/JsonHashTableBase.cpp
Normal file
36
JsonGenerator/JsonHashTableBase.cpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "JsonHashTable.h"
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Generator;
|
||||||
|
|
||||||
|
size_t JsonHashTableBase::printTo(Print& p) const
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
n += p.write('{');
|
||||||
|
|
||||||
|
// NB: the code has been optimized for a small size on a 8-bit AVR
|
||||||
|
|
||||||
|
const KeyValuePair* current = items;
|
||||||
|
for (int i = count; i > 0; i--)
|
||||||
|
{
|
||||||
|
n += current->key.printTo(p);
|
||||||
|
n += p.write(':');
|
||||||
|
n += current->value.printTo(p);
|
||||||
|
|
||||||
|
current++;
|
||||||
|
|
||||||
|
if (i > 1)
|
||||||
|
{
|
||||||
|
n += p.write(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n += p.write('}');
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
62
JsonGenerator/JsonHashTableBase.h
Normal file
62
JsonGenerator/JsonHashTableBase.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonObjectBase.h"
|
||||||
|
#include "EscapedString.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Generator
|
||||||
|
{
|
||||||
|
class JsonHashTableBase : public JsonObjectBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void add(const char* key, T value)
|
||||||
|
{
|
||||||
|
if (count >= capacity) return;
|
||||||
|
|
||||||
|
items[count].key.set(key);
|
||||||
|
items[count].value.set(value);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int DIGITS>
|
||||||
|
void add(const char* key, double value)
|
||||||
|
{
|
||||||
|
if (count >= capacity) return;
|
||||||
|
|
||||||
|
items[count].key.set(key);
|
||||||
|
items[count].value.set<DIGITS>(value);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
using JsonObjectBase::printTo;
|
||||||
|
|
||||||
|
virtual size_t printTo(Print& p) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
struct KeyValuePair
|
||||||
|
{
|
||||||
|
Internals::EscapedString key;
|
||||||
|
Internals::JsonValue value;
|
||||||
|
};
|
||||||
|
|
||||||
|
JsonHashTableBase(KeyValuePair* items, int capacity)
|
||||||
|
: items(items), capacity(capacity), count(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
KeyValuePair* items;
|
||||||
|
int count;
|
||||||
|
int capacity;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
31
JsonGenerator/JsonObjectBase.h
Normal file
31
JsonGenerator/JsonObjectBase.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonValue.h"
|
||||||
|
#include "Print.h"
|
||||||
|
#include "Printable.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Generator
|
||||||
|
{
|
||||||
|
class JsonObjectBase : public Printable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
size_t printTo(char* buffer, size_t bufferSize)
|
||||||
|
{
|
||||||
|
using namespace Internals;
|
||||||
|
|
||||||
|
StringBuilder sb(buffer, bufferSize);
|
||||||
|
return printTo(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t printTo(Print& p) const = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
32
JsonGenerator/JsonValue.cpp
Normal file
32
JsonGenerator/JsonValue.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "EscapedString.h"
|
||||||
|
#include "JsonValue.h"
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Internals;
|
||||||
|
|
||||||
|
size_t JsonValue::printBoolTo(const Content& c, Print& p)
|
||||||
|
{
|
||||||
|
return p.print(c.asBool ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t JsonValue::printLongTo(const Content& c, Print& p)
|
||||||
|
{
|
||||||
|
return p.print(c.asLong);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t JsonValue::printPrintableTo(const Content& c, Print& p)
|
||||||
|
{
|
||||||
|
if (c.asPrintable)
|
||||||
|
return c.asPrintable->printTo(p);
|
||||||
|
else
|
||||||
|
return p.print("null");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t JsonValue::printStringTo(const Content& c, Print& p)
|
||||||
|
{
|
||||||
|
return c.asString.printTo(p);
|
||||||
|
}
|
94
JsonGenerator/JsonValue.h
Normal file
94
JsonGenerator/JsonValue.h
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "EscapedString.h"
|
||||||
|
#include "Printable.h"
|
||||||
|
#include "StringBuilder.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Internals
|
||||||
|
{
|
||||||
|
class JsonValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void set(bool value)
|
||||||
|
{
|
||||||
|
printToImpl = &printBoolTo;
|
||||||
|
content.asBool = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(long value)
|
||||||
|
{
|
||||||
|
printToImpl = &printLongTo;
|
||||||
|
content.asLong = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(int value)
|
||||||
|
{
|
||||||
|
printToImpl = &printLongTo;
|
||||||
|
content.asLong = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(Printable& value)
|
||||||
|
{
|
||||||
|
printToImpl = &printPrintableTo;
|
||||||
|
content.asPrintable = &value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(const char* value)
|
||||||
|
{
|
||||||
|
printToImpl = &printStringTo;
|
||||||
|
content.asString.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(double value)
|
||||||
|
{
|
||||||
|
set<2>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int DIGITS>
|
||||||
|
void set(double value)
|
||||||
|
{
|
||||||
|
printToImpl = &printDoubleTo<DIGITS>;
|
||||||
|
content.asDouble = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t printTo(Print& p) const
|
||||||
|
{
|
||||||
|
// handmade polymorphism
|
||||||
|
return printToImpl(content, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
union Content
|
||||||
|
{
|
||||||
|
bool asBool;
|
||||||
|
long asLong;
|
||||||
|
Printable* asPrintable;
|
||||||
|
EscapedString asString;
|
||||||
|
double asDouble;
|
||||||
|
};
|
||||||
|
|
||||||
|
Content content;
|
||||||
|
|
||||||
|
size_t(*printToImpl)(const Content&, Print&);
|
||||||
|
|
||||||
|
static size_t printBoolTo(const Content&, Print&);
|
||||||
|
static size_t printLongTo(const Content&, Print&);
|
||||||
|
static size_t printPrintableTo(const Content&, Print&);
|
||||||
|
static size_t printStringTo(const Content&, Print&);
|
||||||
|
|
||||||
|
template<int DIGITS>
|
||||||
|
static size_t printDoubleTo(const Content& c, Print& p)
|
||||||
|
{
|
||||||
|
return p.print(c.asDouble, DIGITS);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
28
JsonGenerator/Print.h
Normal file
28
JsonGenerator/Print.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef ARDUINO
|
||||||
|
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
|
||||||
|
// This class reproduces Arduino's Print
|
||||||
|
class Print
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual size_t write(uint8_t) = 0;
|
||||||
|
|
||||||
|
size_t print(const char[]);
|
||||||
|
size_t print(double, int = 2);
|
||||||
|
size_t print(long);
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <Print.h>
|
||||||
|
|
||||||
|
#endif
|
24
JsonGenerator/Printable.h
Normal file
24
JsonGenerator/Printable.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef ARDUINO
|
||||||
|
|
||||||
|
class Print;
|
||||||
|
|
||||||
|
class Printable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual size_t printTo(Print& p) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <Printable.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
167
JsonGenerator/README.md
Normal file
167
JsonGenerator/README.md
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
Arduino JSON library - Generator
|
||||||
|
================================
|
||||||
|
|
||||||
|
This library is a simple JSON encoder for embedded systems.
|
||||||
|
|
||||||
|
It's design to be very lightweight, works without any allocation on the heap (no malloc) and supports nested objects.
|
||||||
|
|
||||||
|
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
||||||
|
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
* Supports nested objects
|
||||||
|
* Elegant API, very easy to use
|
||||||
|
* Fixed memory allocation (no malloc)
|
||||||
|
* Small footprint
|
||||||
|
* Implements Arduino's Printable interface
|
||||||
|
* MIT License
|
||||||
|
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
JsonArray<2> array;
|
||||||
|
array.add<6>(48.756080);
|
||||||
|
array.add<6>(2.302038);
|
||||||
|
|
||||||
|
JsonHashTable<3> root;
|
||||||
|
root.add("sensor", "gps");
|
||||||
|
root.add("time", 1351824120);
|
||||||
|
root.add("data", array);
|
||||||
|
|
||||||
|
Serial.print(root); // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||||
|
|
||||||
|
|
||||||
|
How to use?
|
||||||
|
------------
|
||||||
|
|
||||||
|
### 1. Install the library
|
||||||
|
|
||||||
|
Download the library and extract it to:
|
||||||
|
|
||||||
|
<your Arduino Sketch folder>/libraries/ArduinoJson
|
||||||
|
|
||||||
|
### 2. Import in your sketch
|
||||||
|
|
||||||
|
Just add the following lines at the top of your `.ino` file:
|
||||||
|
|
||||||
|
#include <JsonGenerator.h>
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Generator;
|
||||||
|
|
||||||
|
### 3. Create object tree
|
||||||
|
|
||||||
|
In order to generate a JSON string, you need to build the equivalent object tree. You usually start by the root which can be either an array or an hash-table.
|
||||||
|
|
||||||
|
#### Array
|
||||||
|
|
||||||
|
You create an array with the following line:
|
||||||
|
|
||||||
|
JsonArray<8> array;
|
||||||
|
|
||||||
|
See the little `<8>`? It's a template parameter that gives the capacity of the array, it's the maximum number of elements you can put in it.
|
||||||
|
|
||||||
|
> ##### About the capacity
|
||||||
|
> As stated in the feature list, this library works with a fixed memory allocation.
|
||||||
|
> This means that the size of the object must be know at the compilation time, therefore you can **not** use a variable to set the capacity of the array.
|
||||||
|
|
||||||
|
Then you can add strings, integer, booleans, etc:
|
||||||
|
|
||||||
|
array.add("bazinga!");
|
||||||
|
array.add(42);
|
||||||
|
array.add(true);
|
||||||
|
|
||||||
|
There are two syntaxes for the floating point values:
|
||||||
|
|
||||||
|
array.add<4>(3.1415); // 4 digits: "3.1415"
|
||||||
|
array.add(3.14); // 2 digits: "3.14"
|
||||||
|
|
||||||
|
> ##### About floating point precision
|
||||||
|
> The overload of `add()` with 2 parameters allows you to specify the number of decimals to save in the JSON string.
|
||||||
|
> When you use the overload with one parameter, you use the default number of decimals which is two.
|
||||||
|
> Note that this behavior is the exact same as Arduino's `Print::print(double,int);` which is implemented by `Serial`.
|
||||||
|
> So you may already be familiar with it.
|
||||||
|
|
||||||
|
Finally you can add nested object to the array:
|
||||||
|
|
||||||
|
JsonArray<8> nestedArray;
|
||||||
|
array.add(nestedArray);
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
JsonHashTable<8> nestedHash;
|
||||||
|
array.add(nestedHash);
|
||||||
|
|
||||||
|
#### Hash-table
|
||||||
|
|
||||||
|
You create a hash-table with the following line:
|
||||||
|
|
||||||
|
JsonHashTable<8> hash;
|
||||||
|
|
||||||
|
Like with the array class, there is a template parameter that gives the capacity of the hash-table.
|
||||||
|
|
||||||
|
Then you can add strings, integer, booleans, etc:
|
||||||
|
|
||||||
|
hash.add("key1", "bazinga!");
|
||||||
|
hash.add("key2", 42);
|
||||||
|
hash.add("key3", true);
|
||||||
|
|
||||||
|
As for the arrays, there are two syntaxes for the floating point values:
|
||||||
|
|
||||||
|
array.add<4>("key4", 3.1415); // 4 digits: "3.1415"
|
||||||
|
array.add("key5", 3.14); // 2 digits: "3.14"
|
||||||
|
|
||||||
|
Finally you can add nested objects:
|
||||||
|
|
||||||
|
JsonArray<8> nestedArray;
|
||||||
|
hash.add("key6", nestedArray);
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
JsonHashTable<8> nestedHash;
|
||||||
|
hash.add("key7", nestedHash);
|
||||||
|
|
||||||
|
### 4. Get the JSON string
|
||||||
|
|
||||||
|
There are two ways tho get the resulting JSON string.
|
||||||
|
|
||||||
|
Depending on your project, you may need to dump the string in a classic `char[]` or send it to a stream like `Serial` or `EthernetClient `.
|
||||||
|
|
||||||
|
Both ways are the easy way :-)
|
||||||
|
|
||||||
|
#### Use a classic `char[]`
|
||||||
|
|
||||||
|
Whether you have a `JsonArray` or a `JsonHashTable`, simply call `printTo()` with the destination buffer, like so:
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
array.printTo(buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
#### Send to a stream
|
||||||
|
|
||||||
|
It's very likely that the generated JSON will end up in a stream like `Serial` or `EthernetClient `, so you can save some time and memory by doing this:
|
||||||
|
|
||||||
|
Serial.print(array);
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
array.printTo(Serial);
|
||||||
|
|
||||||
|
> ##### About the Printable interface
|
||||||
|
> `JsonArray` and `JsonHashTable` implement Arduino's `Printable` interface.
|
||||||
|
> This is why you can call `Serial.print()` like in the example above.
|
||||||
|
> You can do the same with any other implementation of `Print`: `HardwareSerial`, `SoftwareSerial`, `LiquidCrystal`, `EthernetClient`, `WiFiClient`...
|
||||||
|
|
||||||
|
|
||||||
|
Memory usage
|
||||||
|
------------
|
||||||
|
|
||||||
|
Here are the size of the main classes of the library.
|
||||||
|
|
||||||
|
This table is for an 8-bit Arduino, types would be bigger on a 32-bit processor.
|
||||||
|
|
||||||
|
| Type | Size in bytes |
|
||||||
|
| ---------------------- | ------------- |
|
||||||
|
| JsonArray<N> | 8 + 6 x N |
|
||||||
|
| JsonHashTable<N> | 8 + 8 x N |
|
17
JsonGenerator/StringBuilder.cpp
Normal file
17
JsonGenerator/StringBuilder.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StringBuilder.h"
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Internals;
|
||||||
|
|
||||||
|
size_t StringBuilder::write(uint8_t c)
|
||||||
|
{
|
||||||
|
if (length >= capacity) return 0;
|
||||||
|
|
||||||
|
buffer[length++] = c;
|
||||||
|
buffer[length] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
31
JsonGenerator/StringBuilder.h
Normal file
31
JsonGenerator/StringBuilder.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Print.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Internals
|
||||||
|
{
|
||||||
|
class StringBuilder : public Print
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StringBuilder(char* buf, int size)
|
||||||
|
: buffer(buf), capacity(size - 1), length(0)
|
||||||
|
{
|
||||||
|
buffer[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t write(uint8_t c);
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* buffer;
|
||||||
|
int capacity;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
97
JsonGeneratorTests/EscapedStringTests.cpp
Normal file
97
JsonGeneratorTests/EscapedStringTests.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "EscapedString.h"
|
||||||
|
#include "StringBuilder.h"
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
using namespace ArduinoJson::Internals;
|
||||||
|
|
||||||
|
namespace JsonGeneratorTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(EscapedStringTests)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
size_t returnValue;
|
||||||
|
EscapedString escapedString;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD(Null)
|
||||||
|
{
|
||||||
|
whenInputIs(0);
|
||||||
|
outputMustBe("null");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(EmptyString)
|
||||||
|
{
|
||||||
|
whenInputIs("");
|
||||||
|
outputMustBe("\"\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(QuotationMark)
|
||||||
|
{
|
||||||
|
whenInputIs("\"");
|
||||||
|
outputMustBe("\"\\\"\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ReverseSolidus)
|
||||||
|
{
|
||||||
|
whenInputIs("\\");
|
||||||
|
outputMustBe("\"\\\\\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Solidus)
|
||||||
|
{
|
||||||
|
whenInputIs("/");
|
||||||
|
outputMustBe("\"/\""); // but the JSON format allows \/
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Backspace)
|
||||||
|
{
|
||||||
|
whenInputIs("\b");
|
||||||
|
outputMustBe("\"\\b\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Formfeed)
|
||||||
|
{
|
||||||
|
whenInputIs("\f");
|
||||||
|
outputMustBe("\"\\f\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Newline)
|
||||||
|
{
|
||||||
|
whenInputIs("\n");
|
||||||
|
outputMustBe("\"\\n\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(CarriageReturn)
|
||||||
|
{
|
||||||
|
whenInputIs("\r");
|
||||||
|
outputMustBe("\"\\r\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(HorizontalTab)
|
||||||
|
{
|
||||||
|
whenInputIs("\t");
|
||||||
|
outputMustBe("\"\\t\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void whenInputIs(const char* input)
|
||||||
|
{
|
||||||
|
StringBuilder sb(buffer, sizeof(buffer));
|
||||||
|
escapedString.set(input);
|
||||||
|
returnValue = escapedString.printTo(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void outputMustBe(const char* expected)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(expected, buffer);
|
||||||
|
Assert::AreEqual(strlen(expected), returnValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
173
JsonGeneratorTests/JsonArrayTests.cpp
Normal file
173
JsonGeneratorTests/JsonArrayTests.cpp
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "JsonArray.h"
|
||||||
|
#include "JsonHashTable.h"
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
using namespace ArduinoJson::Generator;
|
||||||
|
|
||||||
|
namespace JsonGeneratorTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(JsonArrayTests)
|
||||||
|
{
|
||||||
|
JsonArray<2> arr;
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD(Empty)
|
||||||
|
{
|
||||||
|
outputMustBe("[]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Null)
|
||||||
|
{
|
||||||
|
add((char*)0);
|
||||||
|
|
||||||
|
outputMustBe("[null]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneString)
|
||||||
|
{
|
||||||
|
add("hello");
|
||||||
|
|
||||||
|
outputMustBe("[\"hello\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TwoStrings)
|
||||||
|
{
|
||||||
|
add("hello");
|
||||||
|
add("world");
|
||||||
|
|
||||||
|
outputMustBe("[\"hello\",\"world\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneStringOverCapacity)
|
||||||
|
{
|
||||||
|
add("hello");
|
||||||
|
add("world");
|
||||||
|
add("lost");
|
||||||
|
|
||||||
|
outputMustBe("[\"hello\",\"world\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneDoubleDefaultDigits)
|
||||||
|
{
|
||||||
|
add(3.14159265358979323846);
|
||||||
|
outputMustBe("[3.14]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneDoubleFourDigits)
|
||||||
|
{
|
||||||
|
add<4>(3.14159265358979323846);
|
||||||
|
outputMustBe("[3.1416]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneInteger)
|
||||||
|
{
|
||||||
|
add(1);
|
||||||
|
|
||||||
|
outputMustBe("[1]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TwoIntegers)
|
||||||
|
{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
|
||||||
|
outputMustBe("[1,2]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneIntegerOverCapacity)
|
||||||
|
{
|
||||||
|
add(1);
|
||||||
|
add(2);
|
||||||
|
add(3);
|
||||||
|
|
||||||
|
outputMustBe("[1,2]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneTrue)
|
||||||
|
{
|
||||||
|
add(true);
|
||||||
|
|
||||||
|
outputMustBe("[true]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneFalse)
|
||||||
|
{
|
||||||
|
add(false);
|
||||||
|
|
||||||
|
outputMustBe("[false]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TwoBooleans)
|
||||||
|
{
|
||||||
|
add(false);
|
||||||
|
add(true);
|
||||||
|
|
||||||
|
outputMustBe("[false,true]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneBooleanOverCapacity)
|
||||||
|
{
|
||||||
|
add(false);
|
||||||
|
add(true);
|
||||||
|
add(false);
|
||||||
|
|
||||||
|
outputMustBe("[false,true]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneEmptyNestedArray)
|
||||||
|
{
|
||||||
|
addNested(JsonArray<1>());
|
||||||
|
outputMustBe("[[]]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneEmptyNestedHash)
|
||||||
|
{
|
||||||
|
addNested(JsonHashTable<1>());
|
||||||
|
outputMustBe("[{}]");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneNestedArrayWithOneInteger)
|
||||||
|
{
|
||||||
|
JsonArray<1> nestedArray;
|
||||||
|
nestedArray.add(1);
|
||||||
|
|
||||||
|
addNested(nestedArray);
|
||||||
|
|
||||||
|
outputMustBe("[[1]]");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void addNested(JsonObjectBase& value)
|
||||||
|
{
|
||||||
|
arr.add<JsonObjectBase&>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void add(T value)
|
||||||
|
{
|
||||||
|
arr.add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int DIGITS>
|
||||||
|
void add(double value)
|
||||||
|
{
|
||||||
|
arr.add<DIGITS>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void outputMustBe(const char* expected)
|
||||||
|
{
|
||||||
|
size_t n = arr.printTo(buffer, sizeof(buffer));
|
||||||
|
Assert::AreEqual(expected, buffer);
|
||||||
|
Assert::AreEqual(strlen(expected), n);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
114
JsonGeneratorTests/JsonGeneratorTests.vcxproj
Normal file
114
JsonGeneratorTests/JsonGeneratorTests.vcxproj
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{B9545D97-E084-4A19-8E48-929157064360}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>JsonGeneratorTests</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>$(ProjectDir)/../JsonGenerator;$(IncludePath)</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>$(ProjectDir)/../JsonGenerator;$(IncludePath)</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<UseFullPaths>true</UseFullPaths>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<UseFullPaths>true</UseFullPaths>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\JsonGenerator\EscapedString.cpp" />
|
||||||
|
<ClCompile Include="..\JsonGenerator\JsonArrayBase.cpp" />
|
||||||
|
<ClCompile Include="..\JsonGenerator\JsonHashTableBase.cpp" />
|
||||||
|
<ClCompile Include="..\JsonGenerator\JsonValue.cpp" />
|
||||||
|
<ClCompile Include="..\JsonGenerator\StringBuilder.cpp" />
|
||||||
|
<ClCompile Include="EscapedStringTests.cpp" />
|
||||||
|
<ClCompile Include="JsonArrayTests.cpp" />
|
||||||
|
<ClCompile Include="JsonHashTableTests.cpp" />
|
||||||
|
<ClCompile Include="JsonValueTests.cpp" />
|
||||||
|
<ClCompile Include="Print.cpp" />
|
||||||
|
<ClCompile Include="StringBuilderTests.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\JsonGenerator\EscapedString.h" />
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonArray.h" />
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonArrayBase.h" />
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonHashTable.h" />
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonHashTableBase.h" />
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonObjectBase.h" />
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonValue.h" />
|
||||||
|
<ClInclude Include="..\JsonGenerator\Print.h" />
|
||||||
|
<ClInclude Include="..\JsonGenerator\Printable.h" />
|
||||||
|
<ClInclude Include="..\JsonGenerator\StringBuilder.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
84
JsonGeneratorTests/JsonGeneratorTests.vcxproj.filters
Normal file
84
JsonGeneratorTests/JsonGeneratorTests.vcxproj.filters
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="JsonArrayTests.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="JsonHashTableTests.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="JsonValueTests.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\JsonGenerator\JsonValue.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\JsonGenerator\StringBuilder.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="StringBuilderTests.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Print.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\JsonGenerator\EscapedString.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\JsonGenerator\JsonHashTableBase.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\JsonGenerator\JsonArrayBase.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="EscapedStringTests.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonArray.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonHashTable.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonObjectBase.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonValue.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonGenerator\Print.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonGenerator\Printable.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonGenerator\StringBuilder.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonGenerator\EscapedString.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonHashTableBase.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonGenerator\JsonArrayBase.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
124
JsonGeneratorTests/JsonHashTableTests.cpp
Normal file
124
JsonGeneratorTests/JsonHashTableTests.cpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "JsonArray.h"
|
||||||
|
#include "JsonHashTable.h"
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
using namespace ArduinoJson::Generator;
|
||||||
|
|
||||||
|
namespace JsonGeneratorTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(JsonHashTableTests)
|
||||||
|
{
|
||||||
|
JsonHashTable<2> hash;
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD(Empty)
|
||||||
|
{
|
||||||
|
outputMustBe("{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneString)
|
||||||
|
{
|
||||||
|
add("key", "value");
|
||||||
|
outputMustBe("{\"key\":\"value\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TwoStrings)
|
||||||
|
{
|
||||||
|
add("key1", "value1");
|
||||||
|
add("key2", "value2");
|
||||||
|
|
||||||
|
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneStringOverCapacity)
|
||||||
|
{
|
||||||
|
add("key1", "value1");
|
||||||
|
add("key2", "value2");
|
||||||
|
add("key3", "value3");
|
||||||
|
|
||||||
|
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneInteger)
|
||||||
|
{
|
||||||
|
add("key", 1);
|
||||||
|
outputMustBe("{\"key\":1}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneDoubleFourDigits)
|
||||||
|
{
|
||||||
|
add<4>("key", 3.14159265358979323846);
|
||||||
|
outputMustBe("{\"key\":3.1416}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneDoubleDefaultDigits)
|
||||||
|
{
|
||||||
|
add("key", 3.14159265358979323846);
|
||||||
|
outputMustBe("{\"key\":3.14}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneNull)
|
||||||
|
{
|
||||||
|
add("key", (char*) 0);
|
||||||
|
outputMustBe("{\"key\":null}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneTrue)
|
||||||
|
{
|
||||||
|
add("key", true);
|
||||||
|
outputMustBe("{\"key\":true}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneFalse)
|
||||||
|
{
|
||||||
|
add("key", false);
|
||||||
|
outputMustBe("{\"key\":false}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneEmptyNestedArray)
|
||||||
|
{
|
||||||
|
addNested("key", JsonArray<1>());
|
||||||
|
outputMustBe("{\"key\":[]}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneEmptyNestedHash)
|
||||||
|
{
|
||||||
|
addNested("key", JsonHashTable<1>());
|
||||||
|
outputMustBe("{\"key\":{}}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void addNested(const char* key, JsonObjectBase& value)
|
||||||
|
{
|
||||||
|
hash.add<JsonObjectBase&>(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void add(const char* key, T value)
|
||||||
|
{
|
||||||
|
hash.add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<int DIGITS>
|
||||||
|
void add(const char* key, double value)
|
||||||
|
{
|
||||||
|
hash.add<DIGITS>(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void outputMustBe(const char* expected)
|
||||||
|
{
|
||||||
|
size_t actual = hash.printTo(buffer, sizeof(buffer));
|
||||||
|
Assert::AreEqual(expected, buffer);
|
||||||
|
Assert::AreEqual(strlen(expected), actual);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
102
JsonGeneratorTests/JsonValueTests.cpp
Normal file
102
JsonGeneratorTests/JsonValueTests.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "StringBuilder.h"
|
||||||
|
#include "JsonValue.h"
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
using namespace ArduinoJson::Internals;
|
||||||
|
|
||||||
|
namespace JsonGeneratorTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(JsonValueTests)
|
||||||
|
{
|
||||||
|
char buffer[1024];
|
||||||
|
size_t returnValue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD(String)
|
||||||
|
{
|
||||||
|
whenInputIs("hello");
|
||||||
|
outputMustBe("\"hello\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Float)
|
||||||
|
{
|
||||||
|
whenInputIs(3.1415f);
|
||||||
|
outputMustBe("3.14");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(DoubleZeroDigits)
|
||||||
|
{
|
||||||
|
whenInputIs<0>(3.14159265358979323846);
|
||||||
|
outputMustBe("3");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(DoubleOneDigit)
|
||||||
|
{
|
||||||
|
whenInputIs<1>(3.14159265358979323846);
|
||||||
|
outputMustBe("3.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(DoubleTwoDigits)
|
||||||
|
{
|
||||||
|
whenInputIs<2>(3.14159265358979323846);
|
||||||
|
outputMustBe("3.14");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Integer)
|
||||||
|
{
|
||||||
|
whenInputIs(314);
|
||||||
|
outputMustBe("314");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Char)
|
||||||
|
{
|
||||||
|
whenInputIs('A');
|
||||||
|
outputMustBe("65");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Short)
|
||||||
|
{
|
||||||
|
whenInputIs((short)314);
|
||||||
|
outputMustBe("314");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Long)
|
||||||
|
{
|
||||||
|
whenInputIs(314159265L);
|
||||||
|
outputMustBe("314159265");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
template<int DIGITS>
|
||||||
|
void whenInputIs(double value)
|
||||||
|
{
|
||||||
|
StringBuilder sb(buffer, sizeof(buffer));
|
||||||
|
JsonValue jsonValue;
|
||||||
|
jsonValue.set<DIGITS>(value);
|
||||||
|
returnValue = jsonValue.printTo(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void whenInputIs(T value)
|
||||||
|
{
|
||||||
|
StringBuilder sb(buffer, sizeof(buffer));
|
||||||
|
JsonValue jsonValue;
|
||||||
|
jsonValue.set(value);
|
||||||
|
returnValue = jsonValue.printTo(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void outputMustBe(const char* expected)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(expected, buffer);
|
||||||
|
Assert::AreEqual(strlen(expected), returnValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
35
JsonGeneratorTests/Print.cpp
Normal file
35
JsonGeneratorTests/Print.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARDUINO
|
||||||
|
|
||||||
|
#include "Print.h"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
size_t Print::print(const char s[])
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
n += write(*s++);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(double value, int digits)
|
||||||
|
{
|
||||||
|
char tmp[32];
|
||||||
|
sprintf(tmp, "%.*lg", digits+1, value);
|
||||||
|
return print(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Print::print(long value)
|
||||||
|
{
|
||||||
|
char tmp[32];
|
||||||
|
sprintf(tmp, "%ld", value);
|
||||||
|
return print(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
85
JsonGeneratorTests/StringBuilderTests.cpp
Normal file
85
JsonGeneratorTests/StringBuilderTests.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "StringBuilder.h"
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
using namespace ArduinoJson::Internals;
|
||||||
|
|
||||||
|
namespace JsonGeneratorTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(StringBuilderTests)
|
||||||
|
{
|
||||||
|
char buffer[20];
|
||||||
|
Print* sb;
|
||||||
|
size_t returnValue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD_INITIALIZE(Initialize)
|
||||||
|
{
|
||||||
|
sb = new StringBuilder(buffer, sizeof(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(InitialState)
|
||||||
|
{
|
||||||
|
outputMustBe("");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OverCapacity)
|
||||||
|
{
|
||||||
|
print("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||||
|
resultMustBe(19);
|
||||||
|
|
||||||
|
print("ABC");
|
||||||
|
resultMustBe(0);
|
||||||
|
|
||||||
|
outputMustBe("ABCDEFGHIJKLMNOPQRS");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(EmptyString)
|
||||||
|
{
|
||||||
|
print("");
|
||||||
|
resultMustBe(0);
|
||||||
|
outputMustBe("");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneString)
|
||||||
|
{
|
||||||
|
print("ABCD");
|
||||||
|
resultMustBe(4);
|
||||||
|
outputMustBe("ABCD");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TwoStrings)
|
||||||
|
{
|
||||||
|
print("ABCD");
|
||||||
|
resultMustBe(4);
|
||||||
|
|
||||||
|
print("EFGH");
|
||||||
|
resultMustBe(4);
|
||||||
|
|
||||||
|
outputMustBe("ABCDEFGH");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void print(const char* value)
|
||||||
|
{
|
||||||
|
returnValue = sb->print(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void outputMustBe(const char* expected)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(expected, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resultMustBe(size_t expected)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(expected, returnValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* malloc-free JSON parser for Arduino
|
|
||||||
* Benoit Blanchon 2014 - MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __JSONHASHTABLE_H
|
|
||||||
#define __JSONHASHTABLE_H
|
|
||||||
|
|
||||||
#include "JsonObjectBase.h"
|
|
||||||
|
|
||||||
class JsonArray;
|
|
||||||
|
|
||||||
class JsonHashTable : public JsonObjectBase
|
|
||||||
{
|
|
||||||
template <int N>
|
|
||||||
friend class JsonParser;
|
|
||||||
|
|
||||||
friend class JsonArray;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
JsonHashTable() {}
|
|
||||||
|
|
||||||
bool containsKey(const char* key);
|
|
||||||
|
|
||||||
JsonArray getArray(const char* key);
|
|
||||||
bool getBool(const char* key);
|
|
||||||
double getDouble(const char* key);
|
|
||||||
JsonHashTable getHashTable(const char* key);
|
|
||||||
long getLong(const char* key);
|
|
||||||
char* getString(const char* key);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
JsonHashTable(char* json, jsmntok_t* tokens);
|
|
||||||
jsmntok_t* getToken(const char* key);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* malloc-free JSON parser for Arduino
|
|
||||||
* Benoit Blanchon 2014
|
|
||||||
* MIT License
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __JSONOBJECTBASE_H
|
|
||||||
#define __JSONOBJECTBASE_H
|
|
||||||
|
|
||||||
#include "utility/jsmn.h"
|
|
||||||
|
|
||||||
class JsonObjectBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
JsonObjectBase()
|
|
||||||
{
|
|
||||||
makeInvalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool success()
|
|
||||||
{
|
|
||||||
return json != 0 && tokens != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
JsonObjectBase(char* json, jsmntok_t* tokens)
|
|
||||||
{
|
|
||||||
this->json = json;
|
|
||||||
this->tokens = tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeInvalid()
|
|
||||||
{
|
|
||||||
json = 0;
|
|
||||||
tokens = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getNestedTokenCount(jsmntok_t* token);
|
|
||||||
|
|
||||||
bool getBoolFromToken(jsmntok_t* token);
|
|
||||||
double getDoubleFromToken(jsmntok_t* token);
|
|
||||||
long getLongFromToken(jsmntok_t* token);
|
|
||||||
char* getStringFromToken(jsmntok_t* token);
|
|
||||||
|
|
||||||
char* json;
|
|
||||||
jsmntok_t* tokens;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
11
JsonParser.cpp
Normal file
11
JsonParser.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* malloc-free JSON parser for Arduino
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This file is here to help the Arduino IDE find the .cpp files
|
||||||
|
|
||||||
|
#include "JsonParser/JsonArray.cpp"
|
||||||
|
#include "JsonParser/JsonHashTable.cpp"
|
||||||
|
#include "JsonParser/JsonObjectBase.cpp"
|
||||||
|
#include "JsonParser/Jsmn.cpp"
|
65
JsonParser.h
65
JsonParser.h
@ -3,67 +3,4 @@
|
|||||||
* Benoit Blanchon 2014 - MIT License
|
* Benoit Blanchon 2014 - MIT License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __JSONPARSER_H
|
#include "JsonParser/JsonParser.h"
|
||||||
#define __JSONPARSER_H
|
|
||||||
|
|
||||||
#include "JsonHashTable.h"
|
|
||||||
#include "JsonArray.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The JSON parser.
|
|
||||||
*
|
|
||||||
* You need to specifiy the number of token to be allocated for that parser.
|
|
||||||
* Values from 16 to 32 are recommended.
|
|
||||||
* The parser size will be MAX_TOKEN*8 bytes.
|
|
||||||
* Don't forget that the memory size of standard Arduino board is only 2KB
|
|
||||||
*
|
|
||||||
* CAUTION: JsonArray and JsonHashTable contain pointers to tokens of the
|
|
||||||
* JsonParser, so they need the JsonParser to be in memory to work.
|
|
||||||
* As a result, you must not create JsonArray and JsonHashTable that have a
|
|
||||||
* longer life that the JsonParser.
|
|
||||||
*/
|
|
||||||
template <int MAX_TOKENS>
|
|
||||||
class JsonParser
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse the JSON string and return a array.
|
|
||||||
*
|
|
||||||
* The content of the string may be altered to add '\0' at the
|
|
||||||
* end of string tokens
|
|
||||||
*/
|
|
||||||
JsonArray parseArray(char* json)
|
|
||||||
{
|
|
||||||
return JsonArray(json, parse(json));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse the JSON string and return a array.
|
|
||||||
*
|
|
||||||
* The content of the string may be altered to add '\0' at the
|
|
||||||
* end of string tokens
|
|
||||||
*/
|
|
||||||
JsonHashTable parseHashTable(char* json)
|
|
||||||
{
|
|
||||||
return JsonHashTable(json, parse(json));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
jsmntok_t* parse(char* json)
|
|
||||||
{
|
|
||||||
jsmn_parser parser;
|
|
||||||
jsmn_init(&parser);
|
|
||||||
|
|
||||||
if (JSMN_SUCCESS != jsmn_parse(&parser, json, tokens, MAX_TOKENS))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
jsmntok_t tokens[MAX_TOKENS];
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
* malloc-free JSON parser for Arduino
|
* Arduino JSON library
|
||||||
* Benoit Blanchon 2014 - MIT License
|
* Benoit Blanchon 2014 - MIT License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "JsonArray.h"
|
#include "JsonArray.h"
|
||||||
#include "JsonHashTable.h"
|
#include "JsonHashTable.h"
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Parser;
|
||||||
|
|
||||||
JsonArray::JsonArray(char* json, jsmntok_t* tokens)
|
JsonArray::JsonArray(char* json, jsmntok_t* tokens)
|
||||||
: JsonObjectBase(json, tokens)
|
: JsonObjectBase(json, tokens)
|
||||||
{
|
{
|
||||||
if (tokens[0].type != JSMN_ARRAY)
|
if (tokens == 0 || tokens[0].type != JSMN_ARRAY)
|
||||||
makeInvalid();
|
makeInvalid();
|
||||||
}
|
}
|
||||||
|
|
45
JsonParser/JsonArray.h
Normal file
45
JsonParser/JsonArray.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonObjectBase.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Parser
|
||||||
|
{
|
||||||
|
class JsonHashTable;
|
||||||
|
|
||||||
|
class JsonArray : public JsonObjectBase
|
||||||
|
{
|
||||||
|
template <int N>
|
||||||
|
friend class JsonParser;
|
||||||
|
|
||||||
|
friend class JsonHashTable;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
JsonArray() {}
|
||||||
|
|
||||||
|
int getLength()
|
||||||
|
{
|
||||||
|
return tokens != 0 ? tokens[0].size : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonArray getArray(int index);
|
||||||
|
bool getBool(int index);
|
||||||
|
double getDouble(int index);
|
||||||
|
JsonHashTable getHashTable(int index);
|
||||||
|
long getLong(int index);
|
||||||
|
char* getString(int index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
JsonArray(char* json, jsmntok_t* tokens);
|
||||||
|
jsmntok_t* getToken(int index);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* malloc-free JSON parser for Arduino
|
* Arduino JSON library
|
||||||
* Benoit Blanchon 2014 - MIT License
|
* Benoit Blanchon 2014 - MIT License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h> // for strcmp()
|
||||||
#include "JsonArray.h"
|
#include "JsonArray.h"
|
||||||
#include "JsonHashTable.h"
|
#include "JsonHashTable.h"
|
||||||
|
|
||||||
#include <string.h> // for strcmp()
|
using namespace ArduinoJson::Parser;
|
||||||
|
|
||||||
JsonHashTable::JsonHashTable(char* json, jsmntok_t* tokens)
|
JsonHashTable::JsonHashTable(char* json, jsmntok_t* tokens)
|
||||||
: JsonObjectBase(json, tokens)
|
: JsonObjectBase(json, tokens)
|
||||||
{
|
{
|
||||||
if (tokens[0].type != JSMN_OBJECT)
|
if (tokens == 0 || tokens[0].type != JSMN_OBJECT)
|
||||||
makeInvalid();
|
makeInvalid();
|
||||||
}
|
}
|
||||||
|
|
42
JsonParser/JsonHashTable.h
Normal file
42
JsonParser/JsonHashTable.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonObjectBase.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Parser
|
||||||
|
{
|
||||||
|
class JsonArray;
|
||||||
|
|
||||||
|
class JsonHashTable : public JsonObjectBase
|
||||||
|
{
|
||||||
|
template <int N>
|
||||||
|
friend class JsonParser;
|
||||||
|
|
||||||
|
friend class JsonArray;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
JsonHashTable() {}
|
||||||
|
|
||||||
|
bool containsKey(const char* key);
|
||||||
|
|
||||||
|
JsonArray getArray(const char* key);
|
||||||
|
bool getBool(const char* key);
|
||||||
|
double getDouble(const char* key);
|
||||||
|
JsonHashTable getHashTable(const char* key);
|
||||||
|
long getLong(const char* key);
|
||||||
|
char* getString(const char* key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
JsonHashTable(char* json, jsmntok_t* tokens);
|
||||||
|
jsmntok_t* getToken(const char* key);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
* malloc-free JSON parser for Arduino
|
* Arduino JSON library
|
||||||
* Benoit Blanchon 2014
|
* Benoit Blanchon 2014 - MIT License
|
||||||
* MIT License
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include "JsonObjectBase.h"
|
|
||||||
|
|
||||||
#include <stdlib.h> // for strtol, strtod
|
#include <stdlib.h> // for strtol, strtod
|
||||||
|
#include "JsonObjectBase.h"
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Parser;
|
||||||
|
|
||||||
int JsonObjectBase::getNestedTokenCount(jsmntok_t* token)
|
int JsonObjectBase::getNestedTokenCount(jsmntok_t* token)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int end = token->end;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
for (int i = 0; i < token->size; i++)
|
token++;
|
||||||
|
|
||||||
|
while (token->start < end)
|
||||||
{
|
{
|
||||||
count += 1 + getNestedTokenCount(token + 1 + i);
|
token++;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
53
JsonParser/JsonObjectBase.h
Normal file
53
JsonParser/JsonObjectBase.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "jsmn.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Parser
|
||||||
|
{
|
||||||
|
class JsonObjectBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
JsonObjectBase()
|
||||||
|
{
|
||||||
|
makeInvalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success()
|
||||||
|
{
|
||||||
|
return json != 0 && tokens != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
JsonObjectBase(char* json, jsmntok_t* tokens)
|
||||||
|
{
|
||||||
|
this->json = json;
|
||||||
|
this->tokens = tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeInvalid()
|
||||||
|
{
|
||||||
|
json = 0;
|
||||||
|
tokens = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getNestedTokenCount(jsmntok_t* token);
|
||||||
|
|
||||||
|
bool getBoolFromToken(jsmntok_t* token);
|
||||||
|
double getDoubleFromToken(jsmntok_t* token);
|
||||||
|
long getLongFromToken(jsmntok_t* token);
|
||||||
|
char* getStringFromToken(jsmntok_t* token);
|
||||||
|
|
||||||
|
char* json;
|
||||||
|
jsmntok_t* tokens;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
71
JsonParser/JsonParser.h
Normal file
71
JsonParser/JsonParser.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonHashTable.h"
|
||||||
|
#include "JsonArray.h"
|
||||||
|
|
||||||
|
namespace ArduinoJson
|
||||||
|
{
|
||||||
|
namespace Parser
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The JSON parser.
|
||||||
|
*
|
||||||
|
* You need to specifiy the number of token to be allocated for that parser.
|
||||||
|
* Values from 16 to 32 are recommended.
|
||||||
|
* The parser size will be MAX_TOKEN*8 bytes.
|
||||||
|
* Don't forget that the memory size of standard Arduino board is only 2KB
|
||||||
|
*
|
||||||
|
* CAUTION: JsonArray and JsonHashTable contain pointers to tokens of the
|
||||||
|
* JsonParser, so they need the JsonParser to be in memory to work.
|
||||||
|
* As a result, you must not create JsonArray and JsonHashTable that have a
|
||||||
|
* longer life that the JsonParser.
|
||||||
|
*/
|
||||||
|
template <int MAX_TOKENS>
|
||||||
|
class JsonParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the JSON string and return a array.
|
||||||
|
*
|
||||||
|
* The content of the string may be altered to add '\0' at the
|
||||||
|
* end of string tokens
|
||||||
|
*/
|
||||||
|
JsonArray parseArray(char* json)
|
||||||
|
{
|
||||||
|
return JsonArray(json, parse(json));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the JSON string and return a array.
|
||||||
|
*
|
||||||
|
* The content of the string may be altered to add '\0' at the
|
||||||
|
* end of string tokens
|
||||||
|
*/
|
||||||
|
JsonHashTable parseHashTable(char* json)
|
||||||
|
{
|
||||||
|
return JsonHashTable(json, parse(json));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
jsmntok_t* parse(char* json)
|
||||||
|
{
|
||||||
|
jsmn_parser parser;
|
||||||
|
jsmn_init(&parser);
|
||||||
|
|
||||||
|
if (JSMN_SUCCESS != jsmn_parse(&parser, json, tokens, MAX_TOKENS))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
jsmntok_t tokens[MAX_TOKENS];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
404
JsonParser/README.md
Normal file
404
JsonParser/README.md
Normal file
@ -0,0 +1,404 @@
|
|||||||
|
Arduino JSON library - Parser
|
||||||
|
=============================
|
||||||
|
|
||||||
|
This library is an thin C++ wrapper around the *jsmn* tokenizer: http://zserge.com/jsmn.html
|
||||||
|
|
||||||
|
It's design to be very lightweight, works without any allocation on the heap (no malloc) and supports nested objects.
|
||||||
|
|
||||||
|
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
||||||
|
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
|
||||||
|
* Based on the well-proven [jsmn](http://zserge.com/jsmn.html) tokenizer
|
||||||
|
* Supports nested objects
|
||||||
|
* Elegant API, very easy to use
|
||||||
|
* Fixed memory allocation (no malloc)
|
||||||
|
* Small footprint
|
||||||
|
* MIT License
|
||||||
|
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||||
|
|
||||||
|
JsonParser<32> parser;
|
||||||
|
|
||||||
|
JsonHashTable root = parser.parseHashTable(json);
|
||||||
|
|
||||||
|
char* sensor = root.getString("sensor");
|
||||||
|
|
||||||
|
long time = root.getLong("time");
|
||||||
|
|
||||||
|
JsonArray coords = root.getArray("data");
|
||||||
|
|
||||||
|
|
||||||
|
How to use ?
|
||||||
|
-------------
|
||||||
|
|
||||||
|
### 1. Install the library
|
||||||
|
|
||||||
|
Download the library and extract it to:
|
||||||
|
|
||||||
|
<your Arduino Sketch folder>/libraries/ArduinoJson
|
||||||
|
|
||||||
|
### 2. Import in your sketch
|
||||||
|
|
||||||
|
Just add the following lines at the top of your `.ino` file:
|
||||||
|
|
||||||
|
#include <JsonParser.h>
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Parser;
|
||||||
|
|
||||||
|
### 3. Create a parser
|
||||||
|
|
||||||
|
To extract data from the JSON string, you need to create a `JsonParser`, and specify the number of token you allocate for the parser itself:
|
||||||
|
|
||||||
|
JsonParser<32> parser;
|
||||||
|
|
||||||
|
> #### How to choose the number of tokens ?
|
||||||
|
|
||||||
|
> A token is an element of the JSON object: either a key, a value, an hash-table or an array.
|
||||||
|
> As an example the `char json[]` on the top of this page contains 12 tokens (don't forget to count 1 for the whole object and 1 more for the array itself).
|
||||||
|
|
||||||
|
> The more tokens you allocate, the more complex the JSON can be, but also the more memory is occupied.
|
||||||
|
> Each token takes 8 bytes, so `sizeof(JsonParser<32>)` is 256 bytes which is quite big in an Arduino with only 2KB of RAM.
|
||||||
|
> Don't forget that you also have to store the JSON string in RAM and it's probably big.
|
||||||
|
|
||||||
|
> 32 tokens may seem small, but it's very decent for an 8-bit processor, you wouldn't get better results with other JSON libraries.
|
||||||
|
|
||||||
|
### 4. Extract data
|
||||||
|
|
||||||
|
To use this library, you need to know beforehand what is the type of data contained in the JSON string, which is very likely.
|
||||||
|
|
||||||
|
The root object has to be either a hash-table (like `{"key":"value"}`) or an array (like `[1,2]`).
|
||||||
|
|
||||||
|
The nested objects can be either arrays, booleans, hash-tables, numbers or strings.
|
||||||
|
If you need other type, you can get the string value and parse it yourself.
|
||||||
|
|
||||||
|
#### Hash-table
|
||||||
|
|
||||||
|
Consider we have a `char json[]` containing to the following JSON string:
|
||||||
|
|
||||||
|
{
|
||||||
|
"Name":"Blanchon",
|
||||||
|
"Skills":[
|
||||||
|
"C",
|
||||||
|
"C++",
|
||||||
|
"C#"],
|
||||||
|
"Age":32,
|
||||||
|
"Online":true
|
||||||
|
}
|
||||||
|
|
||||||
|
In this case the root object of the JSON string is a hash-table, so you need to extract a `JsonHashTable`:
|
||||||
|
|
||||||
|
JsonHashTable root = parser.parseHashTable(json);
|
||||||
|
|
||||||
|
To check if the parsing was successful, you must check:
|
||||||
|
|
||||||
|
if (!root.success())
|
||||||
|
{
|
||||||
|
// Parsing fail: could be an invalid JSON, or too many tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
And then extract the member you need:
|
||||||
|
|
||||||
|
char* name = hashTable.getString("Name");
|
||||||
|
|
||||||
|
JsonArray skills = hashTable.getArray("Skills");
|
||||||
|
|
||||||
|
int age = hashTable.getLong("Age");
|
||||||
|
|
||||||
|
bool online = hashTable.getBool("Online");
|
||||||
|
|
||||||
|
#### Array
|
||||||
|
|
||||||
|
Consider we have a `char json[]` containing to the following JSON string:
|
||||||
|
|
||||||
|
[
|
||||||
|
[ 1.2, 3.4 ],
|
||||||
|
[ 5.6, 7.8 ]
|
||||||
|
]
|
||||||
|
|
||||||
|
In this case the root object of the JSON string is an array, so you need to extract a `JsonArray`:
|
||||||
|
|
||||||
|
JsonArray root = parser.parseArray(json);
|
||||||
|
|
||||||
|
To check if the parsing was successful, you must check:
|
||||||
|
|
||||||
|
if (!root.success())
|
||||||
|
{
|
||||||
|
// Parsing fail: could be an invalid JSON, or too many tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
And then extract the content by its index in the array:
|
||||||
|
|
||||||
|
JsonArray row0 = root.getArray(0);
|
||||||
|
double a = row0.getDouble(0);
|
||||||
|
|
||||||
|
or simply:
|
||||||
|
|
||||||
|
double a = root.getArray(0).getDouble(0);
|
||||||
|
|
||||||
|
|
||||||
|
Common pitfalls
|
||||||
|
---------------
|
||||||
|
|
||||||
|
### 1. Not enough tokens
|
||||||
|
|
||||||
|
By design, the library has no way to tell you why `JsonParser::parseArray()` or `JsonParser::parseHashTable()` failed.
|
||||||
|
|
||||||
|
There are basically two reasons why they may fail:
|
||||||
|
|
||||||
|
1. the JSON string is invalid
|
||||||
|
2. the JSON string contains more tokens that the parser can store
|
||||||
|
|
||||||
|
So, if you are sure the JSON string is correct and you still can't parse it, you should slightly increase the number of token of the parser.
|
||||||
|
|
||||||
|
### 2. Not enough memory
|
||||||
|
|
||||||
|
You may go into unpredictable trouble if you allocate more memory than your processor really has.
|
||||||
|
It's a very common issue in embedded development.
|
||||||
|
|
||||||
|
To diagnose this, look at every big objects in you code and sum their size to check that they fit in RAM.
|
||||||
|
|
||||||
|
For example, don't do this:
|
||||||
|
|
||||||
|
char json[1024]; // 1 KB
|
||||||
|
JsonParser<64> parser; // 512 B
|
||||||
|
|
||||||
|
because it may be too big for a processor with only 2 KB: you need free memory to store other variables and the call stack.
|
||||||
|
|
||||||
|
That is why an 8-bit processor is not able to parse long and complex JSON strings.
|
||||||
|
|
||||||
|
### 3. JsonParser not in memory
|
||||||
|
|
||||||
|
To reduce the memory consumption, `JsonArray` and `JsonHashTable` contains pointer to the token that are inside the `JsonParser`. This can only work if the `JsonParser` is still in memory.
|
||||||
|
|
||||||
|
For example, don't do this:
|
||||||
|
|
||||||
|
JsonArray getArray(char* json)
|
||||||
|
{
|
||||||
|
JsonParser<16> parser;
|
||||||
|
return parser.parseArray(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
because the local variable `parser` will be *removed* from memory when the function `getArray()` returns, and the pointer inside `JsonArray` will point to an invalid location.
|
||||||
|
|
||||||
|
### 4. JSON string is altered
|
||||||
|
|
||||||
|
This will probably never be an issue, but you need to be aware of this feature.
|
||||||
|
|
||||||
|
When you pass a `char[]` to `JsonParser::parseArray()` or `JsonParser::parseHashTable()`, the content of the string will be altered to add `\0` at the end of the tokens.
|
||||||
|
|
||||||
|
This is because we want functions like `JsonArray::getString()` to return a null-terminating string without any memory allocation.
|
||||||
|
|
||||||
|
|
||||||
|
Memory usage
|
||||||
|
------------
|
||||||
|
|
||||||
|
Here are the size of the main classes of the library.
|
||||||
|
|
||||||
|
This table is for an 8-bit Arduino, types would be bigger on a 32-bit processor.
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Size in bytes</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Parser<N></td>
|
||||||
|
<td>8 x N</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonArray</td>
|
||||||
|
<td>4</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonHashTable</td>
|
||||||
|
<td>4</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
Code size
|
||||||
|
---------
|
||||||
|
|
||||||
|
Theses tables has been created by analyzing the map file generated by AVR-GCC after adding `-Wl,-Map,foo.map` to the command line.
|
||||||
|
|
||||||
|
As you'll see the code size is between 1680 and 3528 bytes, depending on the features you use.
|
||||||
|
|
||||||
|
### Minimum setup
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Function</th>
|
||||||
|
<th>Size in bytes</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>strcmp(char*,char*)</td>
|
||||||
|
<td>18</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>jsmn_init(jsmn_parser*)</td>
|
||||||
|
<td>20</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>jsmn_parse(jsmn_parser*, char const*, jsmntok_t*, unsigned int)</td>
|
||||||
|
<td>960</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonParser::parse(char*)</td>
|
||||||
|
<td>106</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonObjectBase::getNestedTokenCount(jsmntok_t*)</td>
|
||||||
|
<td>84</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonObjectBase::getStringFromToken(jsmntok_t*)</td>
|
||||||
|
<td>68</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonArray::JsonArray(char*, jsmntok_t*)</td>
|
||||||
|
<td>42</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonArray::getToken(int)</td>
|
||||||
|
<td>112</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonArray::getString(int)</td>
|
||||||
|
<td>18</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonHashTable::JsonHashTable(char*, jsmntok_t*)</td>
|
||||||
|
<td>42</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonHashTable::getToken(char*)</td>
|
||||||
|
<td>180</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonHashTable::getString(char*)</td>
|
||||||
|
<td>18</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>TOTAL</td>
|
||||||
|
<td>1680</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
### Additional space to parse nested objects
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Function</th>
|
||||||
|
<th>Size in bytes</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonArray::getArray(int)</td>
|
||||||
|
<td>42</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonArray::getHashTable(int)</td>
|
||||||
|
<td>64</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonHashTable::getArray(char*)</td>
|
||||||
|
<td>64</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonHashTable::getHashTable(char*)</td>
|
||||||
|
<td>42</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>TOTAL</td>
|
||||||
|
<td>212</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
### Additional space to parse `bool` values
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Function</th>
|
||||||
|
<th>Size in bytes</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonObjectBase::getBoolFromToken(jsmntok_t*)</td>
|
||||||
|
<td>82</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonArray::getBool(int)</td>
|
||||||
|
<td>18</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonHashTable::getBool(char*)</td>
|
||||||
|
<td>18</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>TOTAL</td>
|
||||||
|
<td>130</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
### Additional space to parse `double` values
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Function</th>
|
||||||
|
<th>Size in bytes</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>strtod(char*,int)</td>
|
||||||
|
<td>704</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonObjectBase::getDoubleFromToken(jsmntok_t*)</td>
|
||||||
|
<td>44</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonArray::getDouble(int)</td>
|
||||||
|
<td>18</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonHashTable::getDouble(char*)</td>
|
||||||
|
<td>18</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>TOTAL</td>
|
||||||
|
<td>796</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
### Additional space to parse `long` values
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Function</th>
|
||||||
|
<th>Size in bytes</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>strtol(char*,char**,int)</td>
|
||||||
|
<td>606</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonObjectBase::getLongFromToken(jsmntok_t*)</td>
|
||||||
|
<td>56</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonArray::getLong(int)</td>
|
||||||
|
<td>18</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>JsonHashTable::getLong(char*)</td>
|
||||||
|
<td>18</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>TOTAL</td>
|
||||||
|
<td>710</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
107
JsonParserTests/JsonParserTests.vcxproj
Normal file
107
JsonParserTests/JsonParserTests.vcxproj
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{4DD596EF-0185-4AB4-A3C2-F20C496F7806}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>ArduinoJsonParserTests</RootNamespace>
|
||||||
|
<ProjectName>JsonParserTests</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<UseOfMfc>false</UseOfMfc>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<IncludePath>$(VC_IncludePath);..</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<UseFullPaths>true</UseFullPaths>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<UseFullPaths>true</UseFullPaths>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\JsonParser\jsmn.cpp" />
|
||||||
|
<ClCompile Include="..\JsonParser\JsonArray.cpp" />
|
||||||
|
<ClCompile Include="..\JsonParser\JsonHashTable.cpp" />
|
||||||
|
<ClCompile Include="..\JsonParser\JsonObjectBase.cpp" />
|
||||||
|
<ClCompile Include="TestArrayExample.cpp" />
|
||||||
|
<ClCompile Include="TestArrays.cpp" />
|
||||||
|
<ClCompile Include="TestHashTableExample.cpp" />
|
||||||
|
<ClCompile Include="TestGbathreeStrings.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\JsonParser\jsmn.h" />
|
||||||
|
<ClInclude Include="..\JsonParser\JsonArray.h" />
|
||||||
|
<ClInclude Include="..\JsonParser\JsonHashTable.h" />
|
||||||
|
<ClInclude Include="..\JsonParser\JsonObjectBase.h" />
|
||||||
|
<ClInclude Include="..\JsonParser\JsonParser.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
60
JsonParserTests/JsonParserTests.vcxproj.filters
Normal file
60
JsonParserTests/JsonParserTests.vcxproj.filters
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="TestHashTableExample.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="TestArrayExample.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="TestGbathreeStrings.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="TestArrays.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\JsonParser\jsmn.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\JsonParser\JsonArray.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\JsonParser\JsonHashTable.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\JsonParser\JsonObjectBase.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\JsonParser\jsmn.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonParser\JsonArray.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonParser\JsonHashTable.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonParser\JsonObjectBase.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\JsonParser\JsonParser.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
56
JsonParserTests/TestArrayExample.cpp
Normal file
56
JsonParserTests/TestArrayExample.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "JsonParser.h"
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
using namespace ArduinoJson::Parser;
|
||||||
|
|
||||||
|
namespace ArduinoJsonParserTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(TestArrayExample)
|
||||||
|
{
|
||||||
|
char json[128];
|
||||||
|
JsonParser<32> parser;
|
||||||
|
JsonArray array;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD_INITIALIZE(Initialize)
|
||||||
|
{
|
||||||
|
strcpy(json, "[[1.2,3.4],[5.6,7.8]]");
|
||||||
|
array = parser.parseArray(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Array_Success_ReturnsTrue)
|
||||||
|
{
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Array_GetLength_Returns2)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(2, array.getLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Array_GetArray0_ReturnsInnerArray0)
|
||||||
|
{
|
||||||
|
JsonArray innerArray = array.getArray(0);
|
||||||
|
|
||||||
|
Assert::AreEqual(2, innerArray.getLength());
|
||||||
|
Assert::AreEqual(1.2, innerArray.getDouble(0));
|
||||||
|
Assert::AreEqual(3.4, innerArray.getDouble(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Array_GetArray1_ReturnsInnerArray1)
|
||||||
|
{
|
||||||
|
JsonArray innerArray = array.getArray(1);
|
||||||
|
|
||||||
|
Assert::AreEqual(2, innerArray.getLength());
|
||||||
|
Assert::AreEqual(5.6, innerArray.getDouble(0));
|
||||||
|
Assert::AreEqual(7.8, innerArray.getDouble(1));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
147
JsonParserTests/TestArrays.cpp
Normal file
147
JsonParserTests/TestArrays.cpp
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "JsonParser.h"
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
using namespace ArduinoJson::Parser;
|
||||||
|
|
||||||
|
namespace ArduinoJsonParserTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(TestArrays)
|
||||||
|
{
|
||||||
|
JsonParser<32> parser;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD(EmptyString)
|
||||||
|
{
|
||||||
|
char json[] = "";
|
||||||
|
|
||||||
|
JsonArray array = parser.parseArray(json);
|
||||||
|
Assert::IsFalse(array.success());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(EmptyArray)
|
||||||
|
{
|
||||||
|
char json[] = "[]";
|
||||||
|
|
||||||
|
JsonArray array = parser.parseArray(json);
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TooFewClosingBrackets)
|
||||||
|
{
|
||||||
|
char json[] = "[[]";
|
||||||
|
|
||||||
|
JsonArray array = parser.parseArray(json);
|
||||||
|
Assert::IsFalse(array.success());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TooManyClosingBrackets)
|
||||||
|
{
|
||||||
|
char json[] = "[]]";
|
||||||
|
|
||||||
|
JsonArray array = parser.parseArray(json);
|
||||||
|
Assert::IsFalse(array.success());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneDimensionArray)
|
||||||
|
{
|
||||||
|
char json [] = "[0,0]";
|
||||||
|
|
||||||
|
JsonArray array = parser.parseArray(json);
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
Assert::AreEqual(2, array.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(0L, array.getLong(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TwoDimensionsArray)
|
||||||
|
{
|
||||||
|
char json[] = "[[0,0],[0,0]]";
|
||||||
|
|
||||||
|
JsonArray array1 = parser.parseArray(json);
|
||||||
|
Assert::IsTrue(array1.success());
|
||||||
|
Assert::AreEqual(2, array1.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
JsonArray array2 = array1.getArray(i);
|
||||||
|
|
||||||
|
Assert::AreEqual(2, array2.getLength());
|
||||||
|
|
||||||
|
for (int j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(0L, array2.getLong(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TreeDimensionsArray)
|
||||||
|
{
|
||||||
|
char json[] = "[[[0,0],[0,0]],[[0,0],[0,0]]]";
|
||||||
|
|
||||||
|
JsonArray array1 = parser.parseArray(json);
|
||||||
|
Assert::IsTrue(array1.success());
|
||||||
|
Assert::AreEqual(2, array1.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
JsonArray array2 = array1.getArray(i);
|
||||||
|
|
||||||
|
Assert::AreEqual(2, array2.getLength());
|
||||||
|
|
||||||
|
for (int j = 0; j < 2; j++)
|
||||||
|
{
|
||||||
|
JsonArray array3 = array2.getArray(j);
|
||||||
|
|
||||||
|
Assert::AreEqual(2, array3.getLength());
|
||||||
|
|
||||||
|
for (int k = 0; k < 2; k++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(0L, array3.getLong(k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(OneDimensionArrayInHashTable)
|
||||||
|
{
|
||||||
|
char json[] = "{a:[0,0],b:[0,0]}";
|
||||||
|
|
||||||
|
JsonHashTable root = parser.parseHashTable(json);
|
||||||
|
Assert::IsTrue(root.success());
|
||||||
|
|
||||||
|
JsonArray arrayA = root.getArray("a");
|
||||||
|
Assert::IsTrue(arrayA.success());
|
||||||
|
Assert::AreEqual(2, arrayA.getLength());
|
||||||
|
|
||||||
|
JsonArray arrayB = root.getArray("b");
|
||||||
|
Assert::IsTrue(arrayB.success());
|
||||||
|
Assert::AreEqual(2, arrayB.getLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(TwoDimensionsArrayInHashTable)
|
||||||
|
{
|
||||||
|
char json[] = "{a:[[0],[0]],b:[[0],[0]]}";
|
||||||
|
|
||||||
|
JsonHashTable root = parser.parseHashTable(json);
|
||||||
|
Assert::IsTrue(root.success());
|
||||||
|
|
||||||
|
JsonArray arrayA = root.getArray("a");
|
||||||
|
Assert::IsTrue(arrayA.success());
|
||||||
|
Assert::AreEqual(2, arrayA.getLength());
|
||||||
|
|
||||||
|
JsonArray arrayB = root.getArray("b");
|
||||||
|
Assert::IsTrue(arrayB.success());
|
||||||
|
Assert::AreEqual(2, arrayB.getLength());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
244
JsonParserTests/TestGbathreeStrings.cpp
Normal file
244
JsonParserTests/TestGbathreeStrings.cpp
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "JsonParser.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
using namespace ArduinoJson::Parser;
|
||||||
|
|
||||||
|
namespace ArduinoJsonParserTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(TestGbathreeSample1)
|
||||||
|
{
|
||||||
|
char json[1024];
|
||||||
|
JsonParser<200> parser;
|
||||||
|
JsonHashTable root;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD_INITIALIZE(Initialize)
|
||||||
|
{
|
||||||
|
// BUG described here:
|
||||||
|
// http://forum.arduino.cc/index.php?topic=172578.msg1608219#msg1608219
|
||||||
|
strcpy(json, "{ \"protocol_name\":\"fluorescence\",\"repeats\":1,\"wait\":0,\"averages\":1,\"measurements\":3,\"meas2_light\":15,\"meas1_baseline\":0,\"act_light\":20,\"pulsesize\":25,\"pulsedistance\":10000,\"actintensity1\":50,\"actintensity2\":255,\"measintensity\":255,\"calintensity\":255,\"pulses\":[50,50,50],\"act\":[2,1,2,2],\"red\":[2,2,2,2],\"detectors\":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]],\"alta\":[2,2,2,2],\"altb\":[2,2,2,2],\"measlights\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]],\"measlights2\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]],\"altc\":[2,2,2,2],\"altd\":[2,2,2,2]}");
|
||||||
|
root = parser.parseHashTable(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Root)
|
||||||
|
{
|
||||||
|
Assert::IsTrue(root.success());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(ProtocolName)
|
||||||
|
{
|
||||||
|
string protocol_name = root.getString("protocol_name");
|
||||||
|
Assert::AreEqual(string("fluorescence"), protocol_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Repeats)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(1L, root.getLong("repeats"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Wait)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(0L, root.getLong("wait"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Measurements)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(3L, root.getLong("measurements"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Meas2_Light)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(15L, root.getLong("meas2_light"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Meas1_Baseline)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(0L, root.getLong("meas1_baseline"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Act_Light)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(20L, root.getLong("act_light"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Pulsesize)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(25L, root.getLong("pulsesize"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Pulsedistance)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(10000L, root.getLong("pulsedistance"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Actintensity1)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(50L, root.getLong("actintensity1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Actintensity2)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(255L, root.getLong("actintensity2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Measintensity)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(255L, root.getLong("measintensity"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Calintensity)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(255L, root.getLong("calintensity"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Pulses)
|
||||||
|
{
|
||||||
|
// "pulses":[50,50,50]
|
||||||
|
|
||||||
|
JsonArray array = root.getArray("pulses");
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
|
||||||
|
Assert::AreEqual(3, array.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(50L, array.getLong(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Act)
|
||||||
|
{
|
||||||
|
// "act":[2,1,2,2]
|
||||||
|
|
||||||
|
JsonArray array = root.getArray("act");
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
|
||||||
|
Assert::AreEqual(4, array.getLength());
|
||||||
|
Assert::AreEqual(2L, array.getLong(0));
|
||||||
|
Assert::AreEqual(1L, array.getLong(1));
|
||||||
|
Assert::AreEqual(2L, array.getLong(2));
|
||||||
|
Assert::AreEqual(2L, array.getLong(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Detectors)
|
||||||
|
{
|
||||||
|
// "detectors":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]]
|
||||||
|
|
||||||
|
JsonArray array = root.getArray("detectors");
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
Assert::AreEqual(4, array.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(4, array.getArray(i).getLength());
|
||||||
|
|
||||||
|
for (int j = 0; j < 4; j++)
|
||||||
|
Assert::AreEqual(34L, array.getArray(i).getLong(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Alta)
|
||||||
|
{
|
||||||
|
// alta:[2,2,2,2]
|
||||||
|
|
||||||
|
JsonArray array = root.getArray("alta");
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
|
||||||
|
Assert::AreEqual(4, array.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(2L, array.getLong(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Altb)
|
||||||
|
{
|
||||||
|
// altb:[2,2,2,2]
|
||||||
|
|
||||||
|
JsonArray array = root.getArray("altb");
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
|
||||||
|
Assert::AreEqual(4, array.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(2L, array.getLong(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Measlights)
|
||||||
|
{
|
||||||
|
// "measlights":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
|
||||||
|
|
||||||
|
JsonArray array = root.getArray("measlights");
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
Assert::AreEqual(4, array.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(4, array.getArray(i).getLength());
|
||||||
|
|
||||||
|
for (int j = 0; j < 4; j++)
|
||||||
|
Assert::AreEqual(15L, array.getArray(i).getLong(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Measlights2)
|
||||||
|
{
|
||||||
|
// "measlights2":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
|
||||||
|
|
||||||
|
JsonArray array = root.getArray("measlights2");
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
Assert::AreEqual(4, array.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(4, array.getArray(i).getLength());
|
||||||
|
|
||||||
|
for (int j = 0; j < 4; j++)
|
||||||
|
Assert::AreEqual(15L, array.getArray(i).getLong(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Altc)
|
||||||
|
{
|
||||||
|
// altc:[2,2,2,2]
|
||||||
|
|
||||||
|
JsonArray array = root.getArray("altc");
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
|
||||||
|
Assert::AreEqual(4, array.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(2L, array.getLong(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(Altd)
|
||||||
|
{
|
||||||
|
// altd:[2,2,2,2]
|
||||||
|
|
||||||
|
JsonArray array = root.getArray("altd");
|
||||||
|
Assert::IsTrue(array.success());
|
||||||
|
|
||||||
|
Assert::AreEqual(4, array.getLength());
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
Assert::AreEqual(2L, array.getLong(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
25
JsonParserTests/TestHashGenerator.cpp
Normal file
25
JsonParserTests/TestHashGenerator.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
|
||||||
|
namespace ArduinoJsonParserTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(TestHashGenerator)
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD(TestMethod1)
|
||||||
|
{
|
||||||
|
JsonArray<5> arr;
|
||||||
|
arr.Add(1);
|
||||||
|
arr.Add("Hi!");
|
||||||
|
|
||||||
|
JsonHashTable<4> hash;
|
||||||
|
hash.Add("key1", 1);
|
||||||
|
hash.Add("key2", "Hello!");
|
||||||
|
hash.Add("key3", arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
67
JsonParserTests/TestHashTableExample.cpp
Normal file
67
JsonParserTests/TestHashTableExample.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUnitTest.h"
|
||||||
|
#include "JsonParser.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
using namespace ArduinoJson::Parser;
|
||||||
|
|
||||||
|
namespace ArduinoJsonParserTests
|
||||||
|
{
|
||||||
|
TEST_CLASS(TestHashTableExample)
|
||||||
|
{
|
||||||
|
char json[128];
|
||||||
|
JsonParser<32> parser;
|
||||||
|
JsonHashTable hashTable;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
TEST_METHOD_INITIALIZE(Initialize)
|
||||||
|
{
|
||||||
|
strcpy(json, "{\"Name\":\"Blanchon\",\"Skills\":[\"C\",\"C++\",\"C#\"],\"Age\":32,\"Online\":true}");
|
||||||
|
hashTable = parser.parseHashTable(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(HashTable_Success_ReturnsTrue)
|
||||||
|
{
|
||||||
|
Assert::IsTrue(hashTable.success());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(HashTable_GetString_ReturnsExpectedValue)
|
||||||
|
{
|
||||||
|
string name = hashTable.getString("Name");
|
||||||
|
Assert::AreEqual(name, string("Blanchon"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(HashTable_GetArray_ReturnsExpectedValue)
|
||||||
|
{
|
||||||
|
JsonArray skills = hashTable.getArray("Skills");
|
||||||
|
|
||||||
|
string skill0 = skills.getString(0);
|
||||||
|
Assert::AreEqual(skill0, string("C"));
|
||||||
|
|
||||||
|
string skill1 = skills.getString(1);
|
||||||
|
Assert::AreEqual(skill1, string("C++"));
|
||||||
|
|
||||||
|
string skill2 = skills.getString(2);
|
||||||
|
Assert::AreEqual(skill2, string("C#"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(HashTable_GetLong_ReturnsExpectedValue)
|
||||||
|
{
|
||||||
|
int age = hashTable.getLong("Age");
|
||||||
|
Assert::AreEqual(32, age);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(HashTable_GetBool_ReturnsExpectedValue)
|
||||||
|
{
|
||||||
|
bool online = hashTable.getBool("Online");
|
||||||
|
Assert::AreEqual(true, online);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
423
README.md
423
README.md
@ -1,409 +1,56 @@
|
|||||||
An efficient JSON parser for Arduino
|
Arduino JSON library
|
||||||
====================================
|
====================
|
||||||
|
|
||||||
This library is an thin C++ wrapper around the *jsmn* tokenizer: http://zserge.com/jsmn.html
|
*A simple and efficient JSON library for embedded systems.*
|
||||||
|
|
||||||
It's design to be very lightweight, works without any allocation on the heap (no malloc) and supports nested objects.
|
It's design to be very lightweight, works without any allocation on the heap (no malloc).
|
||||||
|
|
||||||
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library on any other C++ project.
|
|
||||||
|
|
||||||
|
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* Based on the well-proven [jsmn](http://zserge.com/jsmn.html) tokenizer
|
* JSON decoding: [more details here](/JsonParser/)
|
||||||
* Supports nested objects
|
* JSON encoding: [more details here](/JsonGenerator/)
|
||||||
* Works with fixed memory allocation : no `malloc()`
|
* Elegant API, very easy to use
|
||||||
* Low footprint
|
* Fixed memory allocation (no malloc)
|
||||||
|
* Small footprint
|
||||||
* MIT License
|
* MIT License
|
||||||
|
|
||||||
|
Feature comparison
|
||||||
|
------------------
|
||||||
|
|
||||||
Example
|
| Library | Memory allocation | Nested objects | Parser size | Encoder size |
|
||||||
-------
|
| ------------ | ----------------- | -------------- | ----------- | ------------- |
|
||||||
|
| Arduino JSON | static | yes | 2616 Bytes | 628 bytes |
|
||||||
|
| json-arduino | dynamic | no | 3348 (+28%) | not supported |
|
||||||
|
| aJson | dynamic | yes | 5088 (+94%) | 4678 (+640%) |
|
||||||
|
|
||||||
char* json = "{\"Name\":\"Blanchon\",\"Skills\":[\"C\",\"C++\",\"C#\"],\"Age\":32,\"Online\":true}";
|
"Parser size" was measured with a program parsing `{"sensor":"outdoor","value":25.6}`.
|
||||||
|
For each library, I wrote a program that extracts a string and a float. I subtracted the size of a program doing the same without any JSON parsing involved. [Source files are here](https://gist.github.com/bblanchon/e8ba914a7109f3642c0f).
|
||||||
|
|
||||||
JsonParser<32> parser;
|
"Encoder size" was measured with a program generating `{"sensor":"outdoor","value":25.6}`.
|
||||||
|
[Source files are here](https://gist.github.com/bblanchon/60224e9dcfeab4ddc7e9).
|
||||||
|
|
||||||
JsonHashTable hashTable = parser.parseHashTable(json);
|
In each case the target platform was an Arduino Duemilanove and Arduino IDE 1.0.5 was used.
|
||||||
|
|
||||||
if (!hashTable.success())
|
Links: [json-arduino](https://github.com/not404/json-arduino), [aJson](https://github.com/interactive-matter/aJson)
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* name = hashTable.getString("Name");
|
Testimonials
|
||||||
|
|
||||||
JsonArray skills = hashTable.getArray("Skills");
|
|
||||||
|
|
||||||
int age = hashTable.getLong("Age");
|
|
||||||
|
|
||||||
bool online = hashTable.getBool("Online");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
How to use ?
|
|
||||||
-------------
|
|
||||||
|
|
||||||
### 1. Install the library
|
|
||||||
|
|
||||||
Download the library and extract it to:
|
|
||||||
|
|
||||||
<your Arduino Sketch folder>/libraries/ArduinoJsonParser
|
|
||||||
|
|
||||||
### 2. Import in your sketch
|
|
||||||
|
|
||||||
Just add the following line on the top of your `.ino` file:
|
|
||||||
|
|
||||||
#include <JsonParser.h>
|
|
||||||
|
|
||||||
### 3. Create a parser
|
|
||||||
|
|
||||||
To extract data from the JSON string, you need to create a `JsonParser`, and specify the number of token you allocate for the parser itself:
|
|
||||||
|
|
||||||
JsonParser<32> parser;
|
|
||||||
|
|
||||||
> #### How to choose the number of tokens ?
|
|
||||||
|
|
||||||
> A token is an element of the JSON object: either a key, a value, an hash-table or an array.
|
|
||||||
> As an example the `char* json` on the top of this page contains 12 tokens (don't forget to count 1 for the whole object and 1 more for the array itself).
|
|
||||||
|
|
||||||
> The more tokens you allocate, the more complex the JSON can be, but also the more memory is occupied.
|
|
||||||
> Each token takes 8 bytes, so `sizeof(JsonParser<32>)` is 256 bytes which is quite big in an Arduino with only 2KB of RAM.
|
|
||||||
> Don't forget that you also have to store the JSON string in RAM and it's probably big.
|
|
||||||
|
|
||||||
> 32 tokens may seem small, but it's very decent for an 8-bit processor, you wouldn't get better results with other JSON libraries.
|
|
||||||
|
|
||||||
### 4. Extract data
|
|
||||||
|
|
||||||
To use this library, you need to know beforehand what is the type of data contained in the JSON string, which is very likely.
|
|
||||||
|
|
||||||
The root object has to be either a hash-table (like `{"key":"value"}`) or an array (like `[1,2]`).
|
|
||||||
|
|
||||||
The nested objects can be either arrays, booleans, hash-tables, numbers or strings.
|
|
||||||
If you need other type, you can get the string value and parse it yourself.
|
|
||||||
|
|
||||||
#### Hash-table
|
|
||||||
|
|
||||||
Consider we have a `char* json` pointing to the following JSON string:
|
|
||||||
|
|
||||||
{
|
|
||||||
"Name":"Blanchon",
|
|
||||||
"Skills":[
|
|
||||||
"C",
|
|
||||||
"C++",
|
|
||||||
"C#"],
|
|
||||||
"Age":32,
|
|
||||||
"Online":true
|
|
||||||
}
|
|
||||||
|
|
||||||
In this case the root object of the JSON string is a hash-table, so you need to extract a `JsonHashTable`:
|
|
||||||
|
|
||||||
JsonHashTable root = parser.parseHashTable(json);
|
|
||||||
|
|
||||||
To check if the parsing was successful, you must check:
|
|
||||||
|
|
||||||
if (!root.success())
|
|
||||||
{
|
|
||||||
// Parsing fail: could be an invalid JSON, or too many tokens
|
|
||||||
}
|
|
||||||
|
|
||||||
And then extract the member you need:
|
|
||||||
|
|
||||||
char* name = hashTable.getString("Name");
|
|
||||||
|
|
||||||
JsonArray skills = hashTable.getArray("Skills");
|
|
||||||
|
|
||||||
int age = hashTable.getLong("Age");
|
|
||||||
|
|
||||||
bool online = hashTable.getBool("Online");
|
|
||||||
|
|
||||||
#### Array
|
|
||||||
|
|
||||||
Consider we have a `char* json` pointing to the following JSON string:
|
|
||||||
|
|
||||||
[
|
|
||||||
[ 1.2, 3.4 ],
|
|
||||||
[ 5.6, 7.8 ]
|
|
||||||
]
|
|
||||||
|
|
||||||
In this case the root object of the JSON string is an array, so you need to extract a `JsonArray`:
|
|
||||||
|
|
||||||
JsonArray root = parser.parseArray(json);
|
|
||||||
|
|
||||||
To check if the parsing was successful, you must check:
|
|
||||||
|
|
||||||
if (!root.success())
|
|
||||||
{
|
|
||||||
// Parsing fail: could be an invalid JSON, or too many tokens
|
|
||||||
}
|
|
||||||
|
|
||||||
And then extract the content by its index in the array:
|
|
||||||
|
|
||||||
JsonArray row0 = root.getArray(0);
|
|
||||||
double a = row0.getDouble(0);
|
|
||||||
|
|
||||||
or simply:
|
|
||||||
|
|
||||||
double a = root.getArray(0).getDouble(0);
|
|
||||||
|
|
||||||
|
|
||||||
Common pitfalls
|
|
||||||
---------------
|
|
||||||
|
|
||||||
### 1. Not enough tokens
|
|
||||||
|
|
||||||
By design, the library has no way to tell you why `JsonParser::parseArray()` or `JsonParser::parseHashTable()` failed.
|
|
||||||
|
|
||||||
There are basically two reasons why they may fail:
|
|
||||||
|
|
||||||
1. the JSON string is invalid
|
|
||||||
2. the JSON string contains more tokens that the parser can store
|
|
||||||
|
|
||||||
So, if you are sure the JSON string is correct and you still can't parse it, you should slightly increase the number of token of the parser.
|
|
||||||
|
|
||||||
### 2. Not enough memory
|
|
||||||
|
|
||||||
You may go into unpredictable trouble if you allocate more memory than your processor really has.
|
|
||||||
It's a very common issue in embedded development.
|
|
||||||
|
|
||||||
To diagnose this, look at every big objects in you code and sum their size to check that they fit in RAM.
|
|
||||||
|
|
||||||
For example, don't do this:
|
|
||||||
|
|
||||||
char json[1024]; // 1 KB
|
|
||||||
JsonParser<64> parser; // 512 B
|
|
||||||
|
|
||||||
because it may be too big for a processor with only 2 KB: you need free memory to store other variables and the call stack.
|
|
||||||
|
|
||||||
That is why an 8-bit processor is not able to parse long and complex JSON strings.
|
|
||||||
|
|
||||||
### 3. JsonParser not in memory
|
|
||||||
|
|
||||||
To reduce the memory consumption, `JsonArray` and `JsonHashTable` contains pointer to the token that are inside the `JsonParser`. This can only work if the `JsonParser` is still in memory.
|
|
||||||
|
|
||||||
For example, don't do this:
|
|
||||||
|
|
||||||
JsonArray getArray(char* json)
|
|
||||||
{
|
|
||||||
JsonParser<16> parser;
|
|
||||||
return parser.parseArray(parser);
|
|
||||||
}
|
|
||||||
|
|
||||||
because the local variable `parser` will be *removed* from memory when the function `getArray()` returns, and the pointer inside `JsonArray` will point to an invalid location.
|
|
||||||
|
|
||||||
### 4. JSON string is altered
|
|
||||||
|
|
||||||
This will probably never be an issue, but you need to be aware of this feature.
|
|
||||||
|
|
||||||
When you pass a `char*` to `JsonParser::parseArray()` or `JsonParser::parseHashTable()`, the content of the string will be altered to add `\0` at the end of the tokens.
|
|
||||||
|
|
||||||
This is because we want functions like `JsonArray::getString()` to return a null-terminating string without any memory allocation.
|
|
||||||
|
|
||||||
|
|
||||||
Memory usage
|
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Here are the size of the main classes of the library.
|
From Arduino's Forum user `jflaplante`:
|
||||||
|
> I tried the [aJson and json-arduino] before trying your library. I always ran into memory problem after a while.
|
||||||
|
> I have no such problem so far with your library. It is working perfectly with my web services.
|
||||||
|
|
||||||
This table is for an 8-bit Arduino, types would be bigger on a 32-bit processor.
|
From Arduino's Forum user `gbathree`:
|
||||||
|
> Thanks so much - this is an awesome library! If you want to see what we're doing with it - the project is located at www.photosynq.org.
|
||||||
|
|
||||||
<table>
|
From StackOverflow user `thegreendroid`:
|
||||||
<tr>
|
> It has a really elegant, simple API and it works like a charm on embedded and Windows/Linux platforms. We recently started using this on an embedded project and I can vouch for its quality.
|
||||||
<th>Type</th>
|
|
||||||
<th>Size in bytes</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Parser<N></td>
|
|
||||||
<td>8 x N</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonArray</td>
|
|
||||||
<td>4</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonHashTable</td>
|
|
||||||
<td>4</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
|
Links
|
||||||
|
-----
|
||||||
|
|
||||||
Code size
|
* [The project for which I made me this library](http://blog.benoitblanchon.fr/rfid-payment-terminal/)
|
||||||
---------
|
* [Blog post on the motivation for this library](http://blog.benoitblanchon.fr/arduino-json-parser/)
|
||||||
|
|
||||||
Theses tables has been created by analyzing the map file generated by AVR-GCC after adding `-Wl,-Map,foo.map` to the command line.
|
|
||||||
|
|
||||||
As you'll see the code size if between 1680 and 3528 bytes, depending on the features you use.
|
|
||||||
|
|
||||||
### Minimum setup
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Function</th>
|
|
||||||
<th>Size in bytes</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>strcmp(char*,char*)</td>
|
|
||||||
<td>18</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>jsmn_init(jsmn_parser*)</td>
|
|
||||||
<td>20</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>jsmn_parse(jsmn_parser*, char const*, jsmntok_t*, unsigned int)</td>
|
|
||||||
<td>960</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonParser::parse(char*)</td>
|
|
||||||
<td>106</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonObjectBase::getNestedTokenCount(jsmntok_t*)</td>
|
|
||||||
<td>84</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonObjectBase::getStringFromToken(jsmntok_t*)</td>
|
|
||||||
<td>68</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonArray::JsonArray(char*, jsmntok_t*)</td>
|
|
||||||
<td>42</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonArray::getToken(int)</td>
|
|
||||||
<td>112</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonArray::getString(int)</td>
|
|
||||||
<td>18</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonHashTable::JsonHashTable(char*, jsmntok_t*)</td>
|
|
||||||
<td>42</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonHashTable::getToken(char*)</td>
|
|
||||||
<td>180</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonHashTable::getString(char*)</td>
|
|
||||||
<td>18</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>TOTAL</td>
|
|
||||||
<td>1680</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
### Additional space to parse nested objects
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Function</th>
|
|
||||||
<th>Size in bytes</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonArray::getArray(int)</td>
|
|
||||||
<td>42</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonArray::getHashTable(int)</td>
|
|
||||||
<td>64</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonHashTable::getArray(char*)</td>
|
|
||||||
<td>64</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonHashTable::getHashTable(char*)</td>
|
|
||||||
<td>42</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>TOTAL</td>
|
|
||||||
<td>212</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
### Additional space to parse `bool` values
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Function</th>
|
|
||||||
<th>Size in bytes</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonObjectBase::getBoolFromToken(jsmntok_t*)</td>
|
|
||||||
<td>82</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonArray::getBool(int)</td>
|
|
||||||
<td>18</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonHashTable::getBool(char*)</td>
|
|
||||||
<td>18</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>TOTAL</td>
|
|
||||||
<td>130</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
### Additional space to parse `double` values
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Function</th>
|
|
||||||
<th>Size in bytes</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>strtod(char*,int)</td>
|
|
||||||
<td>704</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonObjectBase::getDoubleFromToken(jsmntok_t*)</td>
|
|
||||||
<td>44</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonArray::getDouble(int)</td>
|
|
||||||
<td>18</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonHashTable::getDouble(char*)</td>
|
|
||||||
<td>18</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>TOTAL</td>
|
|
||||||
<td>796</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
### Additional space to parse `long` values
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Function</th>
|
|
||||||
<th>Size in bytes</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>strtol(char*,char**,int)</td>
|
|
||||||
<td>606</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonObjectBase::getLongFromToken(jsmntok_t*)</td>
|
|
||||||
<td>56</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonArray::getLong(int)</td>
|
|
||||||
<td>18</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>JsonHashTable::getLong(char*)</td>
|
|
||||||
<td>18</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>TOTAL</td>
|
|
||||||
<td>710</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
29
examples/JsonGeneratorExample/JsonGeneratorExample.ino
Normal file
29
examples/JsonGeneratorExample/JsonGeneratorExample.ino
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Arduino JSON library - Generator example
|
||||||
|
* Benoit Blanchon 2014 - MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <JsonGenerator.h>
|
||||||
|
|
||||||
|
using namespace ArduinoJson::Generator;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
JsonArray<2> array;
|
||||||
|
array.add<6>(48.756080); // 6 is the number of decimals to print
|
||||||
|
array.add<6>(2.302038); // if not specified, 2 digits are printed
|
||||||
|
|
||||||
|
JsonHashTable<3> root;
|
||||||
|
root.add("sensor", "gps");
|
||||||
|
root.add("time", 1351824120);
|
||||||
|
root.add("data", array);
|
||||||
|
|
||||||
|
Serial.print(root); // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -1,94 +1,44 @@
|
|||||||
/*
|
/*
|
||||||
* malloc-free JSON parser for Arduino
|
* Arduino JSON library - Parser Example
|
||||||
* Benoit Blanchon 2014 - MIT License
|
* Benoit Blanchon 2014 - MIT License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <JsonParser.h>
|
#include <JsonParser.h>
|
||||||
|
|
||||||
void ParseAnObject()
|
using namespace ArduinoJson::Parser;
|
||||||
{
|
|
||||||
char* json = "{\"Name\":\"Blanchon\",\"Skills\":[\"C\",\"C++\",\"C#\"],\"Age\":32,\"Online\":true}";
|
|
||||||
|
|
||||||
JsonParser<32> parser;
|
|
||||||
|
|
||||||
Serial.print("Parse ");
|
|
||||||
Serial.println(json);
|
|
||||||
|
|
||||||
JsonHashTable hashTable = parser.parseHashTable(json);
|
|
||||||
|
|
||||||
if (!hashTable.success())
|
|
||||||
{
|
|
||||||
Serial.println("JsonParser.parseHashTable() failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* name = hashTable.getString("Name");
|
|
||||||
Serial.print("name=");
|
|
||||||
Serial.println(name);
|
|
||||||
|
|
||||||
JsonArray skills = hashTable.getArray("Skills");
|
|
||||||
Serial.println("skills:");
|
|
||||||
for (int i = 0; i < skills.getLength(); i++)
|
|
||||||
{
|
|
||||||
char* value = skills.getString(i);
|
|
||||||
Serial.print(i);
|
|
||||||
Serial.print(" ");
|
|
||||||
Serial.println(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
int age = hashTable.getLong("Age");
|
|
||||||
Serial.print("age=");
|
|
||||||
Serial.println(age);
|
|
||||||
|
|
||||||
bool online = hashTable.getBool("Online");
|
|
||||||
Serial.print("online=");
|
|
||||||
Serial.println(online);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParseAnArray()
|
|
||||||
{
|
|
||||||
char* json = "[[1.2,3.4],[5.6,7.8]]";
|
|
||||||
|
|
||||||
JsonParser<32> parser;
|
|
||||||
|
|
||||||
Serial.print("Parse ");
|
|
||||||
Serial.println(json);
|
|
||||||
|
|
||||||
JsonArray array = parser.parseArray(json);
|
|
||||||
|
|
||||||
if (!array.success())
|
|
||||||
{
|
|
||||||
Serial.println("JsonParser.parseArray() failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < array.getLength(); i++)
|
|
||||||
{
|
|
||||||
Serial.println(i);
|
|
||||||
|
|
||||||
JsonArray innerArray = array.getArray(i);
|
|
||||||
|
|
||||||
for (int j = 0; j < innerArray.getLength(); j++)
|
|
||||||
{
|
|
||||||
double value = innerArray.getDouble(j);
|
|
||||||
|
|
||||||
Serial.print(" ");
|
|
||||||
Serial.print(j);
|
|
||||||
Serial.print("=");
|
|
||||||
Serial.println(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
|
|
||||||
ParseAnObject();
|
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||||
ParseAnArray();
|
|
||||||
|
JsonParser<16> parser;
|
||||||
|
|
||||||
|
JsonHashTable root = parser.parseHashTable(json);
|
||||||
|
|
||||||
|
if (!root.success())
|
||||||
|
{
|
||||||
|
Serial.println("JsonParser.parseHashTable() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* sensor = root.getString("sensor");
|
||||||
|
Serial.println(sensor);
|
||||||
|
|
||||||
|
long time = root.getLong("time");
|
||||||
|
Serial.println(time);
|
||||||
|
|
||||||
|
JsonArray coords = root.getArray("data");
|
||||||
|
|
||||||
|
for (int i = 0; i < coords.getLength(); i++)
|
||||||
|
{
|
||||||
|
double value = coords.getDouble(i);
|
||||||
|
Serial.println(value, 6);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user