Commit e282e1b6 authored by Kenton Varda's avatar Kenton Varda

Add JSON annotations for encoding Data as base64 or hex.

parent 4311434a
......@@ -840,10 +840,14 @@ R"({ "names-can_contain!anything Really": "foo",
"simpleGroup": {"renamed-grault": "garply"},
"enums": ["qux", "renamed-bar", "foo", "renamed-baz"],
"innerJson": [123, "hello", {"object": true}],
"customFieldHandler": "add-prefix-waldo" })"_kj;
"customFieldHandler": "add-prefix-waldo",
"testBase64": "ZnJlZA==",
"testHex": "706c756768" })"_kj;
static constexpr kj::StringPtr GOLDEN_ANNOTATED_REVERSE =
R"({
"testHex": "706c756768",
"testBase64": "ZnJlZA==",
"customFieldHandler": "add-prefix-waldo",
"innerJson": [123, "hello", {"object": true}],
"enums": ["qux", "renamed-bar", "foo", "renamed-baz"],
......@@ -927,6 +931,9 @@ KJ_TEST("rename fields") {
root.setCustomFieldHandler("waldo");
root.setTestBase64("fred"_kj.asBytes());
root.setTestHex("plugh"_kj.asBytes());
auto encoded = json.encode(root.asReader());
KJ_EXPECT(encoded == GOLDEN_ANNOTATED, encoded);
......
......@@ -74,6 +74,9 @@ struct TestJsonAnnotations {
innerJson @16 :Json.Value;
customFieldHandler @17 :Text;
testBase64 @18 :Data $Json.base64;
testHex @19 :Data $Json.hex;
}
struct TestJsonAnnotations2 {
......
......@@ -31,6 +31,7 @@
#include <kj/function.h>
#include <kj/vector.h>
#include <kj/one-of.h>
#include <kj/encoding.h>
namespace capnp {
......@@ -896,6 +897,32 @@ void JsonCodec::addFieldHandlerImpl(StructSchema::Field field, Type type, Handle
static constexpr uint64_t JSON_NAME_ANNOTATION_ID = 0xfa5b1fd61c2e7c3dull;
static constexpr uint64_t JSON_FLATTEN_ANNOTATION_ID = 0x82d3e852af0336bfull;
static constexpr uint64_t JSON_DISCRIMINATOR_ANNOTATION_ID = 0xcfa794e8d19a0162ull;
static constexpr uint64_t JSON_BASE64_ANNOTATION_ID = 0xd7d879450a253e4bull;
static constexpr uint64_t JSON_HEX_ANNOTATION_ID = 0xf061e22f0ae5c7b5ull;
class JsonCodec::Base64Handler final: public JsonCodec::Handler<capnp::Data> {
public:
void encode(const JsonCodec& codec, capnp::Data::Reader input, JsonValue::Builder output) const {
output.setString(kj::encodeBase64(input));
}
Orphan<capnp::Data> decode(const JsonCodec& codec, JsonValue::Reader input,
Orphanage orphanage) const {
return orphanage.newOrphanCopy(capnp::Data::Reader(kj::decodeBase64(input.getString())));
}
};
class JsonCodec::HexHandler final: public JsonCodec::Handler<capnp::Data> {
public:
void encode(const JsonCodec& codec, capnp::Data::Reader input, JsonValue::Builder output) const {
output.setString(kj::encodeHex(input));
}
Orphan<capnp::Data> decode(const JsonCodec& codec, JsonValue::Reader input,
Orphanage orphanage) const {
return orphanage.newOrphanCopy(capnp::Data::Reader(kj::decodeHex(input.getString())));
}
};
class JsonCodec::AnnotatedHandler final: public JsonCodec::Handler<DynamicStruct> {
public:
......@@ -962,6 +989,18 @@ public:
KJ_REQUIRE(fieldProto.isGroup(), "only unions can have discriminator");
subDiscriminator = anno.getValue().getText();
break;
case JSON_BASE64_ANNOTATION_ID: {
KJ_REQUIRE(field.getType().isData(), "only Data can be marked for base64 encoding");
static Base64Handler handler;
codec.addFieldHandler(field, handler);
break;
}
case JSON_HEX_ANNOTATION_ID: {
KJ_REQUIRE(field.getType().isData(), "only Data can be marked for hex encoding");
static HexHandler handler;
codec.addFieldHandler(field, handler);
break;
}
}
}
......
......@@ -92,3 +92,9 @@ annotation discriminator @0xcfa794e8d19a0162 (struct, union): Text;
# by a special discriminator field with the given name. The value of the discriminator field is
# a string naming which variant is active. This allows the members of the union to have the
# $jsonFlatten annotation.
annotation base64 @0xd7d879450a253e4b (field): Void;
# Place on a field of type `Data` to indicate that its JSON representation is a Base64 string.
annotation hex @0xf061e22f0ae5c7b5 (field): Void;
# Place on a field of type `Data` to indicate that its JSON representation is a hex string.
......@@ -231,6 +231,8 @@ private:
class HandlerBase;
class AnnotatedHandler;
class AnnotatedEnumHandler;
class Base64Handler;
class HexHandler;
class JsonValueHandler;
struct Impl;
......
......@@ -13,4 +13,6 @@
"dependency": {"renamed-foo": "corge"},
"simpleGroup": {"renamed-grault": "garply"},
"enums": ["qux", "renamed-bar", "foo", "renamed-baz"],
"innerJson": [123, "hello", {"object": true}] }
"innerJson": [123, "hello", {"object": true}],
"testBase64": "ZnJlZA==",
"testHex": "706c756768" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment