Refactored the serialization

This commit is contained in:
Benoit Blanchon
2014-10-05 16:25:49 +02:00
parent 31c9ea9b28
commit b6799dc231
10 changed files with 206 additions and 133 deletions

View File

@ -0,0 +1,72 @@
#include "JsonNode.h"
#include "JsonWriter.h"
#include "../JsonArray.h"
#include "../JsonObject.h"
void JsonNode::writeTo(JsonWriter& writer)
{
switch (type)
{
case JSON_ARRAY:
writeArrayTo(writer);
break;
case JSON_OBJECT:
writeObjectTo(writer);
break;
case JSON_STRING:
writer.writeValue(content.asString);
break;
case JSON_INTEGER:
writer.writeValue(content.asInteger);
break;
case JSON_BOOLEAN:
writer.writeValue(content.asBoolean);
break;
case JSON_PROXY:
content.asProxy.target->writeTo(writer);
break;
default: // >= JSON_DOUBLE_0_DECIMALS
writer.writeValue(content.asDouble, type - JSON_DOUBLE_0_DECIMALS);
break;
}
}
void JsonNode::writeArrayTo(JsonWriter& writer)
{
writer.beginArray();
JsonNode* child = content.asContainer.child;
while(child)
{
child->writeTo(writer);
child = child->next;
}
writer.endArray();
}
void JsonNode::writeObjectTo(JsonWriter& writer)
{
writer.beginObject();
JsonNode* child = content.asContainer.child;
while (child)
{
writer.writeKey(child->content.asKey.key);
child->content.asKey.value->writeTo(writer);
child = child->next;
}
writer.endObject();
}

View File

@ -19,10 +19,14 @@ enum JsonNodeType
// etc. // etc.
}; };
class JsonWriter;
struct JsonNode struct JsonNode
{ {
JsonNode* next; JsonNode* next;
JsonNodeType type; JsonNodeType type; // <- TODO: hide
void writeTo(JsonWriter&);
union union
{ {
@ -49,4 +53,8 @@ struct JsonNode
} asProxy; } asProxy;
} content; } content;
private:
inline void writeArrayTo(JsonWriter&);
inline void writeObjectTo(JsonWriter&);
}; };

View File

@ -1,96 +0,0 @@
#include "JsonNodeSerializer.h"
#include "EscapedString.h"
#include "JsonNode.h"
using namespace ArduinoJson::Internals;
size_t JsonNodeSerializer::serialize(const JsonNode* node)
{
if (!node) return 0;
switch (node->type)
{
case JSON_ARRAY:
return serializeArray(node);
case JSON_OBJECT:
return serializeObject(node);
case JSON_STRING:
return EscapedString::printTo(node->content.asString, _sink);
case JSON_INTEGER:
return _sink.print(node->content.asInteger);
case JSON_BOOLEAN:
return _sink.print(node->content.asBoolean ? "true" : "false");
case JSON_PROXY:
return serialize(node->content.asProxy.target);
}
if (node->type >= JSON_DOUBLE_0_DECIMALS)
{
return _sink.print(node->content.asDouble, node->type - JSON_DOUBLE_0_DECIMALS);
}
return 0;
}
size_t JsonNodeSerializer::serializeArray(JsonNode const* node)
{
size_t n = 0;
n += _sink.write('[');
JsonNode* firstChild = node->content.asContainer.child;
for (JsonNode* child = firstChild; child; child = child->next)
{
n += serialize(child);
if (child->next)
{
n += _sink.write(',');
}
}
n += _sink.write(']');
return n;
}
size_t JsonNodeSerializer::serializeObject(const JsonNode* node)
{
size_t n = 0;
n += _sink.write('{');
JsonNode* firstChild = node->content.asContainer.child;
for (JsonNode* child = firstChild; child; child = child->next)
{
n += serializeKeyValue(child);
if (child->next)
{
n += _sink.write(',');
}
}
n += _sink.write('}');
return n;
}
size_t JsonNodeSerializer::serializeKeyValue(JsonNode const* node)
{
const char* childKey = node->content.asKey.key;
JsonNode* childValue = node->content.asKey.value;
return
EscapedString::printTo(childKey, _sink) +
_sink.write(':') +
serialize(childValue);
}

View File

@ -1,23 +0,0 @@
#pragma once
class Print;
struct JsonNode;
class JsonNodeSerializer
{
public:
explicit JsonNodeSerializer(Print& sink)
: _sink(sink)
{
}
size_t serialize(const JsonNode* node);
private:
Print& _sink;
size_t serializeArray(const JsonNode* node);
size_t serializeObject(const JsonNode* node);
size_t serializeKeyValue(const JsonNode* node);
};

View File

@ -0,0 +1,66 @@
#include "JsonWriter.h"
#include "EscapedString.h"
using namespace ArduinoJson::Internals;
void JsonWriter::beginArray()
{
writeCommaIfNeeded();
_length += _sink.write('[');
_isCommaNeeded = false;
}
void JsonWriter::endArray()
{
_length += _sink.write(']');
_isCommaNeeded = true;
}
void JsonWriter::beginObject()
{
writeCommaIfNeeded();
_length += _sink.write('{');
_isCommaNeeded = false;
}
void JsonWriter::endObject()
{
_length += _sink.write('}');
_isCommaNeeded = true;
}
void JsonWriter::writeKey(char const* key)
{
writeCommaIfNeeded();
_length += EscapedString::printTo(key, _sink);
_length += _sink.write(':');
_isCommaNeeded = false;
}
void JsonWriter::writeValue(char const* value)
{
writeCommaIfNeeded();
_length += EscapedString::printTo(value, _sink);
_isCommaNeeded = true;
}
void JsonWriter::writeValue(long value)
{
writeCommaIfNeeded();
_length += _sink.print(value);
_isCommaNeeded = true;
}
void JsonWriter::writeValue(bool value)
{
writeCommaIfNeeded();
_length += _sink.print(value ? "true" : "false");
_isCommaNeeded = true;
}
void JsonWriter::writeValue(double value, int decimals)
{
writeCommaIfNeeded();
_length += _sink.print(value, decimals);
_isCommaNeeded = true;
}

View File

@ -0,0 +1,42 @@
#pragma once
#include "../Arduino/Print.h"
class JsonWriter
{
public:
explicit JsonWriter(Print& sink)
: _sink(sink), _length(0), _isCommaNeeded(false)
{
}
size_t bytesWritten()
{
return _length;
}
void beginArray();
void endArray();
void beginObject();
void endObject();
void writeKey(const char* key);
void writeValue(const char* value);
void writeValue(long value);
void writeValue(bool value);
void writeValue(double value, int decimals);
private:
Print& _sink;
size_t _length;
bool _isCommaNeeded;
void writeCommaIfNeeded()
{
if (_isCommaNeeded)
_length += _sink.write(',');
}
};

View File

@ -1,7 +1,7 @@
#include "JsonContainer.h" #include "JsonContainer.h"
#include "JsonBuffer.h" #include "JsonBuffer.h"
#include "Internals/JsonNodeSerializer.h" #include "Internals/JsonWriter.h"
#include "Internals/StringBuilder.h" #include "Internals/StringBuilder.h"
size_t JsonContainer::printTo(char* buffer, size_t bufferSize) const size_t JsonContainer::printTo(char* buffer, size_t bufferSize) const
@ -12,8 +12,9 @@ size_t JsonContainer::printTo(char* buffer, size_t bufferSize) const
size_t JsonContainer::printTo(Print& p) const size_t JsonContainer::printTo(Print& p) const
{ {
JsonNodeSerializer serializer(p); JsonWriter writer(p);
return serializer.serialize(_node); _node->writeTo(writer);
return writer.bytesWritten();
} }
JsonNode* JsonContainer::createNode(JsonNodeType type) JsonNode* JsonContainer::createNode(JsonNodeType type)

View File

@ -6,7 +6,6 @@
#include "JsonValue.h" #include "JsonValue.h"
#include "Internals/EscapedString.h" #include "Internals/EscapedString.h"
#include "Internals/JsonNode.h" #include "Internals/JsonNode.h"
#include "Internals/JsonNodeSerializer.h"
#include "Internals/StringBuilder.h" #include "Internals/StringBuilder.h"
using namespace ArduinoJson::Internals; using namespace ArduinoJson::Internals;

View File

@ -78,7 +78,7 @@
<ClInclude Include="JsonArray.h" /> <ClInclude Include="JsonArray.h" />
<ClInclude Include="JsonBuffer.h" /> <ClInclude Include="JsonBuffer.h" />
<ClInclude Include="Internals\JsonNode.h" /> <ClInclude Include="Internals\JsonNode.h" />
<ClInclude Include="Internals\JsonNodeSerializer.h" /> <ClInclude Include="Internals\JsonWriter.h" />
<ClInclude Include="JsonContainer.h" /> <ClInclude Include="JsonContainer.h" />
<ClInclude Include="Internals\JsonNodeIterator.h" /> <ClInclude Include="Internals\JsonNodeIterator.h" />
<ClInclude Include="JsonObject.h" /> <ClInclude Include="JsonObject.h" />
@ -90,9 +90,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Internals\EscapedString.cpp" /> <ClCompile Include="Internals\EscapedString.cpp" />
<ClCompile Include="Internals\JsonNode.cpp" />
<ClCompile Include="JsonArray.cpp" /> <ClCompile Include="JsonArray.cpp" />
<ClCompile Include="JsonBuffer.cpp" /> <ClCompile Include="JsonBuffer.cpp" />
<ClCompile Include="Internals\JsonNodeSerializer.cpp" /> <ClCompile Include="Internals\JsonWriter.cpp" />
<ClCompile Include="JsonContainer.cpp" /> <ClCompile Include="JsonContainer.cpp" />
<ClCompile Include="JsonObject.cpp" /> <ClCompile Include="JsonObject.cpp" />
<ClCompile Include="JsonValue.cpp" /> <ClCompile Include="JsonValue.cpp" />

View File

@ -33,9 +33,6 @@
<ClInclude Include="Internals\JsonNode.h"> <ClInclude Include="Internals\JsonNode.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Internals\JsonNodeSerializer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Internals\StringBuilder.h"> <ClInclude Include="Internals\StringBuilder.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -54,6 +51,9 @@
<ClInclude Include="JsonArray.h"> <ClInclude Include="JsonArray.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Internals\JsonWriter.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="JsonObject.cpp"> <ClCompile Include="JsonObject.cpp">
@ -68,9 +68,6 @@
<ClCompile Include="Internals\EscapedString.cpp"> <ClCompile Include="Internals\EscapedString.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Internals\JsonNodeSerializer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Internals\StringBuilder.cpp"> <ClCompile Include="Internals\StringBuilder.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -83,5 +80,11 @@
<ClCompile Include="JsonArray.cpp"> <ClCompile Include="JsonArray.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Internals\JsonNode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Internals\JsonWriter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>