Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
d5e04e32
Commit
d5e04e32
authored
Apr 22, 2016
by
Kenton Varda
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #297 from katreniak/bka-jsonDecode
json: implement decode(... input, DynamicStruct::Builder output)
parents
215fdaa9
95304d03
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
366 additions
and
3 deletions
+366
-3
CONTRIBUTORS
CONTRIBUTORS
+1
-0
json-test.c++
c++/src/capnp/compat/json-test.c++
+159
-0
json.c++
c++/src/capnp/compat/json.c++
+204
-3
json.h
c++/src/capnp/compat/json.h
+2
-0
No files found.
CONTRIBUTORS
View file @
d5e04e32
...
...
@@ -14,6 +14,7 @@ Ben Laurie <ben@links.org>: discovered and responsibly disclosed security bugs
Kamal Marhubi <kamal@marhubi.com>: JSON parser
Oliver Kuckertz <oliver.kuckertz@mologie.de>: FdObserver POLLPRI support
Harris Hancock <vortrab@gmail.com>: MSVC support
Branislav Katreniak <branislav.katreniak@digitalstrom.com>: JSON decode
This file does not list people who maintain their own Cap'n Proto
implementations as separate projects. Those people are awesome too! :)
c++/src/capnp/compat/json-test.c++
View file @
d5e04e32
...
...
@@ -183,6 +183,165 @@ KJ_TEST("encode union") {
KJ_EXPECT
(
json
.
encode
(
root
)
==
"{
\"
before
\"
:
\"
a
\"
,
\"
middle
\"
:44,
\"
bar
\"
:321,
\"
after
\"
:
\"
c
\"
}"
);
}
KJ_TEST
(
"decode all types"
)
{
JsonCodec
json
;
#define CASE(s, f) \
{ \
MallocMessageBuilder message; \
auto root = message.initRoot<TestAllTypes>(); \
json.decode(s, root); \
KJ_EXPECT((f)) \
}
#define CASE_THROW(s, errorMessage) \
{ \
MallocMessageBuilder message; \
auto root = message.initRoot<TestAllTypes>(); \
KJ_EXPECT_THROW_MESSAGE(errorMessage, json.decode(s, root)); \
}
CASE
(
R"({})"
,
root
.
getBoolField
()
==
false
);
CASE
(
R"({"unknownField":7})"
,
root
.
getBoolField
()
==
false
);
CASE
(
R"({"boolField":true})"
,
root
.
getBoolField
()
==
true
);
CASE
(
R"({"int8Field":-128})"
,
root
.
getInt8Field
()
==
-
128
);
CASE
(
R"({"int8Field":"127"})"
,
root
.
getInt8Field
()
==
127
);
CASE_THROW
(
R"({"int8Field":"-129"})"
,
"Value out-of-range"
);
CASE_THROW
(
R"({"int8Field":128})"
,
"Value out-of-range"
);
CASE
(
R"({"int16Field":-32768})"
,
root
.
getInt16Field
()
==
-
32768
);
CASE
(
R"({"int16Field":"32767"})"
,
root
.
getInt16Field
()
==
32767
);
CASE_THROW
(
R"({"int16Field":"-32769"})"
,
"Value out-of-range"
);
CASE_THROW
(
R"({"int16Field":32768})"
,
"Value out-of-range"
);
CASE
(
R"({"int32Field":-2147483648})"
,
root
.
getInt32Field
()
==
-
2147483648
);
CASE
(
R"({"int32Field":"2147483647"})"
,
root
.
getInt32Field
()
==
2147483647
);
CASE
(
R"({"int64Field":-9007199254740992})"
,
root
.
getInt64Field
()
==
-
9007199254740992LL
);
CASE
(
R"({"int64Field":9007199254740991})"
,
root
.
getInt64Field
()
==
9007199254740991LL
);
CASE
(
R"({"int64Field":"-9223372036854775808"})"
,
root
.
getInt64Field
()
==
-
9223372036854775808ULL
);
CASE
(
R"({"int64Field":"9223372036854775807"})"
,
root
.
getInt64Field
()
==
9223372036854775807LL
);
CASE_THROW
(
R"({"int64Field":"-9223372036854775809"})"
,
"Value out-of-range"
);
CASE_THROW
(
R"({"int64Field":"9223372036854775808"})"
,
"Value out-of-range"
);
CASE
(
R"({"uInt8Field":255})"
,
root
.
getUInt8Field
()
==
255
);
CASE
(
R"({"uInt8Field":"0"})"
,
root
.
getUInt8Field
()
==
0
);
CASE_THROW
(
R"({"uInt8Field":"256"})"
,
"Value out-of-range"
);
CASE_THROW
(
R"({"uInt8Field":-1})"
,
"Value out-of-range"
);
CASE
(
R"({"uInt16Field":65535})"
,
root
.
getUInt16Field
()
==
65535
);
CASE
(
R"({"uInt16Field":"0"})"
,
root
.
getUInt16Field
()
==
0
);
CASE_THROW
(
R"({"uInt16Field":"655356"})"
,
"Value out-of-range"
);
CASE_THROW
(
R"({"uInt16Field":-1})"
,
"Value out-of-range"
);
CASE
(
R"({"uInt32Field":4294967295})"
,
root
.
getUInt32Field
()
==
4294967295
);
CASE
(
R"({"uInt32Field":"0"})"
,
root
.
getUInt32Field
()
==
0
);
CASE_THROW
(
R"({"uInt32Field":"42949672956"})"
,
"Value out-of-range"
);
CASE_THROW
(
R"({"uInt32Field":-1})"
,
"Value out-of-range"
);
CASE
(
R"({"uInt64Field":9007199254740991})"
,
root
.
getUInt64Field
()
==
9007199254740991ULL
);
CASE
(
R"({"uInt64Field":"18446744073709551615"})"
,
root
.
getUInt64Field
()
==
18446744073709551615ULL
);
CASE
(
R"({"uInt64Field":"0"})"
,
root
.
getUInt64Field
()
==
0
);
CASE_THROW
(
R"({"uInt64Field":"18446744073709551616"})"
,
"Value out-of-range"
);
CASE
(
R"({"float32Field":0})"
,
root
.
getFloat32Field
()
==
0
);
CASE
(
R"({"float32Field":4.5})"
,
root
.
getFloat32Field
()
==
4.5
);
CASE
(
R"({"float32Field":null})"
,
kj
::
isNaN
(
root
.
getFloat32Field
()));
CASE
(
R"({"float32Field":"nan"})"
,
kj
::
isNaN
(
root
.
getFloat32Field
()));
CASE
(
R"({"float32Field":"nan"})"
,
kj
::
isNaN
(
root
.
getFloat32Field
()));
CASE
(
R"({"float32Field":"Infinity"})"
,
root
.
getFloat32Field
()
==
kj
::
inf
());
CASE
(
R"({"float32Field":"-Infinity"})"
,
root
.
getFloat32Field
()
==
-
kj
::
inf
());
CASE
(
R"({"float64Field":0})"
,
root
.
getFloat64Field
()
==
0
);
CASE
(
R"({"float64Field":4.5})"
,
root
.
getFloat64Field
()
==
4.5
);
CASE
(
R"({"float64Field":null})"
,
kj
::
isNaN
(
root
.
getFloat64Field
()));
CASE
(
R"({"float64Field":"nan"})"
,
kj
::
isNaN
(
root
.
getFloat64Field
()));
CASE
(
R"({"float64Field":"nan"})"
,
kj
::
isNaN
(
root
.
getFloat64Field
()));
CASE
(
R"({"float64Field":"Infinity"})"
,
root
.
getFloat64Field
()
==
kj
::
inf
());
CASE
(
R"({"float64Field":"-Infinity"})"
,
root
.
getFloat64Field
()
==
-
kj
::
inf
());
CASE
(
R"({"textField":"hello"})"
,
kj
::
str
(
"hello"
)
==
root
.
getTextField
());
CASE
(
R"({"dataField":[7,0,122]})"
,
kj
::
heapArray
<
byte
>
({
7
,
0
,
122
}).
asPtr
()
==
root
.
getDataField
());
CASE
(
R"({"structField":null})"
,
root
.
hasStructField
()
==
false
);
CASE
(
R"({"structField":{}})"
,
root
.
hasStructField
()
==
true
);
CASE
(
R"({"structField":{}})"
,
root
.
getStructField
().
getBoolField
()
==
false
);
CASE
(
R"({"structField":{"boolField":false}})"
,
root
.
getStructField
().
getBoolField
()
==
false
);
CASE
(
R"({"structField":{"boolField":true}})"
,
root
.
getStructField
().
getBoolField
()
==
true
);
CASE
(
R"({"enumField":"bar"})"
,
root
.
getEnumField
()
==
TestEnum
::
BAR
);
CASE_THROW
(
R"({"int64Field":"177a"})"
,
"String does not contain valid"
);
CASE_THROW
(
R"({"uInt64Field":"177a"})"
,
"String does not contain valid"
);
CASE_THROW
(
R"({"float64Field":"177a"})"
,
"String does not contain valid"
);
CASE
(
R"({})"
,
root
.
hasBoolList
()
==
false
);
CASE
(
R"({"boolList":null})"
,
root
.
hasBoolList
()
==
false
);
CASE
(
R"({"boolList":[]})"
,
root
.
hasBoolList
()
==
true
);
CASE
(
R"({"boolList":[]})"
,
root
.
getBoolList
().
size
()
==
0
);
CASE
(
R"({"boolList":[false]})"
,
root
.
getBoolList
().
size
()
==
1
);
CASE
(
R"({"boolList":[false]})"
,
root
.
getBoolList
()[
0
]
==
false
);
CASE
(
R"({"boolList":[true]})"
,
root
.
getBoolList
()[
0
]
==
true
);
CASE
(
R"({"int8List":[7]})"
,
root
.
getInt8List
()[
0
]
==
7
);
CASE
(
R"({"int8List":["7"]})"
,
root
.
getInt8List
()[
0
]
==
7
);
CASE
(
R"({"int16List":[7]})"
,
root
.
getInt16List
()[
0
]
==
7
);
CASE
(
R"({"int16List":["7"]})"
,
root
.
getInt16List
()[
0
]
==
7
);
CASE
(
R"({"int32List":[7]})"
,
root
.
getInt32List
()[
0
]
==
7
);
CASE
(
R"({"int32List":["7"]})"
,
root
.
getInt32List
()[
0
]
==
7
);
CASE
(
R"({"int64List":[7]})"
,
root
.
getInt64List
()[
0
]
==
7
);
CASE
(
R"({"int64List":["7"]})"
,
root
.
getInt64List
()[
0
]
==
7
);
CASE
(
R"({"uInt8List":[7]})"
,
root
.
getUInt8List
()[
0
]
==
7
);
CASE
(
R"({"uInt8List":["7"]})"
,
root
.
getUInt8List
()[
0
]
==
7
);
CASE
(
R"({"uInt16List":[7]})"
,
root
.
getUInt16List
()[
0
]
==
7
);
CASE
(
R"({"uInt16List":["7"]})"
,
root
.
getUInt16List
()[
0
]
==
7
);
CASE
(
R"({"uInt32List":[7]})"
,
root
.
getUInt32List
()[
0
]
==
7
);
CASE
(
R"({"uInt32List":["7"]})"
,
root
.
getUInt32List
()[
0
]
==
7
);
CASE
(
R"({"uInt64List":[7]})"
,
root
.
getUInt64List
()[
0
]
==
7
);
CASE
(
R"({"uInt64List":["7"]})"
,
root
.
getUInt64List
()[
0
]
==
7
);
CASE
(
R"({"float32List":[4.5]})"
,
root
.
getFloat32List
()[
0
]
==
4.5
);
CASE
(
R"({"float32List":["4.5"]})"
,
root
.
getFloat32List
()[
0
]
==
4.5
);
CASE
(
R"({"float32List":[null]})"
,
kj
::
isNaN
(
root
.
getFloat32List
()[
0
]));
CASE
(
R"({"float32List":["nan"]})"
,
kj
::
isNaN
(
root
.
getFloat32List
()[
0
]));
CASE
(
R"({"float32List":["infinity"]})"
,
root
.
getFloat32List
()[
0
]
==
kj
::
inf
());
CASE
(
R"({"float32List":["-infinity"]})"
,
root
.
getFloat32List
()[
0
]
==
-
kj
::
inf
());
CASE
(
R"({"float64List":[4.5]})"
,
root
.
getFloat64List
()[
0
]
==
4.5
);
CASE
(
R"({"float64List":["4.5"]})"
,
root
.
getFloat64List
()[
0
]
==
4.5
);
CASE
(
R"({"float64List":[null]})"
,
kj
::
isNaN
(
root
.
getFloat64List
()[
0
]));
CASE
(
R"({"float64List":["nan"]})"
,
kj
::
isNaN
(
root
.
getFloat64List
()[
0
]));
CASE
(
R"({"float64List":["infinity"]})"
,
root
.
getFloat64List
()[
0
]
==
kj
::
inf
());
CASE
(
R"({"float64List":["-infinity"]})"
,
root
.
getFloat64List
()[
0
]
==
-
kj
::
inf
());
CASE
(
R"({"textList":["hello"]})"
,
kj
::
str
(
"hello"
)
==
root
.
getTextList
()[
0
]);
CASE
(
R"({"dataList":[[7,0,122]]})"
,
kj
::
heapArray
<
byte
>
({
7
,
0
,
122
}).
asPtr
()
==
root
.
getDataList
()[
0
]);
CASE
(
R"({"structList":null})"
,
root
.
hasStructList
()
==
false
);
CASE
(
R"({"structList":[null]})"
,
root
.
hasStructList
()
==
true
);
CASE
(
R"({"structList":[null]})"
,
root
.
getStructList
()[
0
].
getBoolField
()
==
false
);
CASE
(
R"({"structList":[{}]})"
,
root
.
getStructList
()[
0
].
getBoolField
()
==
false
);
CASE
(
R"({"structList":[{"boolField":false}]})"
,
root
.
getStructList
()[
0
].
getBoolField
()
==
false
);
CASE
(
R"({"structList":[{"boolField":true}]})"
,
root
.
getStructList
()[
0
].
getBoolField
()
==
true
);
CASE
(
R"({"enumList":["bar"]})"
,
root
.
getEnumList
()[
0
]
==
TestEnum
::
BAR
);
#undef CASE
#undef CASE_THROW
}
KJ_TEST
(
"decode test message"
)
{
MallocMessageBuilder
message
;
auto
root
=
message
.
getRoot
<
TestAllTypes
>
();
initTestMessage
(
root
);
JsonCodec
json
;
auto
encoded
=
json
.
encode
(
root
);
MallocMessageBuilder
decodedMessage
;
auto
decodedRoot
=
decodedMessage
.
initRoot
<
TestAllTypes
>
();
json
.
decode
(
encoded
,
decodedRoot
);
// json encode serializes nan, inf and -inf as null.
auto
float32List
=
decodedRoot
.
getFloat32List
();
auto
float64List
=
decodedRoot
.
getFloat64List
();
KJ_EXPECT
(
kj
::
isNaN
(
float32List
[
1
]));
KJ_EXPECT
(
kj
::
isNaN
(
float32List
[
2
]));
KJ_EXPECT
(
kj
::
isNaN
(
float32List
[
3
]));
KJ_EXPECT
(
kj
::
isNaN
(
float64List
[
1
]));
KJ_EXPECT
(
kj
::
isNaN
(
float64List
[
2
]));
KJ_EXPECT
(
kj
::
isNaN
(
float64List
[
3
]));
float32List
.
set
(
1
,
kj
::
inf
());
float32List
.
set
(
2
,
-
kj
::
inf
());
float32List
.
set
(
3
,
kj
::
nan
());
float64List
.
set
(
1
,
kj
::
inf
());
float64List
.
set
(
2
,
-
kj
::
inf
());
float64List
.
set
(
3
,
kj
::
nan
());
KJ_EXPECT
(
root
.
toString
().
flatten
()
==
decodedRoot
.
toString
().
flatten
());
}
KJ_TEST
(
"basic json decoding"
)
{
// TODO(cleanup): this test is a mess!
JsonCodec
json
;
...
...
c++/src/capnp/compat/json.c++
View file @
d5e04e32
...
...
@@ -379,13 +379,214 @@ void JsonCodec::encodeField(StructSchema::Field field, DynamicValue::Reader inpu
encode
(
input
,
field
.
getType
(),
output
);
}
namespace
{
int64_t
parseInt64
(
kj
::
StringPtr
s
)
{
char
*
endPtr
;
errno
=
0
;
int64_t
value
=
std
::
strtoll
(
s
.
begin
(),
&
endPtr
,
10
);
KJ_REQUIRE
(
endPtr
==
s
.
end
(),
"String does not contain valid number"
,
s
);
KJ_REQUIRE
(
errno
!=
ERANGE
,
"Value out-of-range"
,
s
);
return
value
;
}
uint64_t
parseUInt64
(
kj
::
StringPtr
s
)
{
char
*
endPtr
;
errno
=
0
;
uint64_t
value
=
std
::
strtoull
(
s
.
begin
(),
&
endPtr
,
10
);
KJ_REQUIRE
(
endPtr
==
s
.
end
(),
"String does not contain valid number"
,
s
);
KJ_REQUIRE
(
errno
!=
ERANGE
,
"Value out-of-range"
,
s
);
return
value
;
}
double
parseFloat64
(
kj
::
StringPtr
s
)
{
char
*
endPtr
;
errno
=
0
;
double
value
=
std
::
strtod
(
s
.
begin
(),
&
endPtr
);
KJ_REQUIRE
(
endPtr
==
s
.
end
(),
"String does not contain valid floating number"
,
s
);
return
value
;
}
template
<
typename
SetFn
,
typename
DecodeArrayFn
,
typename
DecodeObjectFn
>
void
decodeField
(
Type
type
,
JsonValue
::
Reader
value
,
SetFn
setFn
,
DecodeArrayFn
decodeArrayFn
,
DecodeObjectFn
decodeObjectFn
)
{
// This code relies on conversions in DynamicValue::Reader::as<T>.
switch
(
type
.
which
())
{
case
schema
:
:
Type
::
VOID
:
break
;
case
schema
:
:
Type
::
BOOL
:
switch
(
value
.
which
())
{
case
JsonValue
:
:
BOOLEAN
:
setFn
(
value
.
getBoolean
());
break
;
default
:
KJ_FAIL_REQUIRE
(
"Expected boolean value"
);
}
break
;
case
schema
:
:
Type
::
INT8
:
case
schema
:
:
Type
::
INT16
:
case
schema
:
:
Type
::
INT32
:
case
schema
:
:
Type
::
INT64
:
// Relies on range check in DynamicValue::Reader::as<IntType>
switch
(
value
.
which
())
{
case
JsonValue
:
:
NUMBER
:
setFn
(
value
.
getNumber
());
break
;
case
JsonValue
:
:
STRING
:
setFn
(
parseInt64
(
value
.
getString
()));
break
;
default
:
KJ_FAIL_REQUIRE
(
"Expected integer value"
);
}
break
;
case
schema
:
:
Type
::
UINT8
:
case
schema
:
:
Type
::
UINT16
:
case
schema
:
:
Type
::
UINT32
:
case
schema
:
:
Type
::
UINT64
:
// Relies on range check in DynamicValue::Reader::as<IntType>
switch
(
value
.
which
())
{
case
JsonValue
:
:
NUMBER
:
setFn
(
value
.
getNumber
());
break
;
case
JsonValue
:
:
STRING
:
setFn
(
parseUInt64
(
value
.
getString
()));
break
;
default
:
KJ_FAIL_REQUIRE
(
"Expected integer value"
);
}
break
;
case
schema
:
:
Type
::
FLOAT32
:
case
schema
:
:
Type
::
FLOAT64
:
switch
(
value
.
which
())
{
case
JsonValue
:
:
NULL_
:
setFn
(
kj
::
nan
());
break
;
case
JsonValue
:
:
NUMBER
:
setFn
(
value
.
getNumber
());
break
;
case
JsonValue
:
:
STRING
:
setFn
(
parseFloat64
(
value
.
getString
()));
break
;
default
:
KJ_FAIL_REQUIRE
(
"Expected float value"
);
}
break
;
case
schema
:
:
Type
::
TEXT
:
switch
(
value
.
which
())
{
case
JsonValue
:
:
STRING
:
setFn
(
value
.
getString
());
break
;
default
:
KJ_FAIL_REQUIRE
(
"Expected text value"
);
}
break
;
case
schema
:
:
Type
::
DATA
:
switch
(
value
.
which
())
{
case
JsonValue
:
:
ARRAY
:
{
auto
array
=
value
.
getArray
();
kj
::
Vector
<
byte
>
data
(
array
.
size
());
for
(
auto
arrayObject
:
array
)
{
auto
x
=
arrayObject
.
getNumber
();
KJ_REQUIRE
(
byte
(
x
)
==
x
,
"Number in byte array is not an integer in [0, 255]"
);
data
.
add
(
byte
(
x
));
}
setFn
(
Data
::
Reader
(
data
.
asPtr
()));
break
;
}
default
:
KJ_FAIL_REQUIRE
(
"Expected data value"
);
}
break
;
case
schema
:
:
Type
::
LIST
:
switch
(
value
.
which
())
{
case
JsonValue
:
:
NULL_
:
// nothing to do
break
;
case
JsonValue
:
:
ARRAY
:
decodeArrayFn
(
value
.
getArray
());
break
;
default
:
KJ_FAIL_REQUIRE
(
"Expected list value"
);
}
break
;
case
schema
:
:
Type
::
ENUM
:
switch
(
value
.
which
())
{
case
JsonValue
:
:
STRING
:
setFn
(
value
.
getString
());
break
;
default
:
KJ_FAIL_REQUIRE
(
"Expected enum value"
);
}
break
;
case
schema
:
:
Type
::
STRUCT
:
switch
(
value
.
which
())
{
case
JsonValue
:
:
NULL_
:
// nothing to do
break
;
case
JsonValue
:
:
OBJECT
:
decodeObjectFn
(
value
.
getObject
());
break
;
default
:
KJ_FAIL_REQUIRE
(
"Expected object value"
);
}
break
;
case
schema
:
:
Type
::
INTERFACE
:
KJ_FAIL_REQUIRE
(
"don't know how to JSON-encode capabilities; "
"JsonCodec::Handler not implemented yet :("
);
case
schema
:
:
Type
::
ANY_POINTER
:
KJ_FAIL_REQUIRE
(
"don't know how to JSON-encode AnyPointer; "
"JsonCodec::Handler not implemented yet :("
);
}
}
}
// namespace
void
JsonCodec
::
decodeArray
(
List
<
JsonValue
>::
Reader
input
,
DynamicList
::
Builder
output
)
const
{
KJ_ASSERT
(
input
.
size
()
==
output
.
size
(),
"Builder was not initialized to input size"
);
auto
type
=
output
.
getSchema
().
getElementType
();
for
(
auto
i
=
0
;
i
<
input
.
size
();
i
++
)
{
decodeField
(
type
,
input
[
i
],
[
&
](
DynamicValue
::
Reader
value
)
{
output
.
set
(
i
,
value
);
},
[
&
](
List
<
JsonValue
>::
Reader
array
)
{
decodeArray
(
array
,
output
.
init
(
i
,
array
.
size
()).
as
<
DynamicList
>
());
},
[
&
](
List
<
JsonValue
::
Field
>::
Reader
object
)
{
decodeObject
(
object
,
output
[
i
].
as
<
DynamicStruct
>
());
});
}
}
void
JsonCodec
::
decodeObject
(
List
<
JsonValue
::
Field
>::
Reader
input
,
DynamicStruct
::
Builder
output
)
const
{
for
(
auto
field
:
input
)
{
KJ_IF_MAYBE
(
fieldSchema
,
output
.
getSchema
().
findFieldByName
(
field
.
getName
()))
{
decodeField
((
*
fieldSchema
).
getType
(),
field
.
getValue
(),
[
&
](
DynamicValue
::
Reader
value
)
{
output
.
set
(
*
fieldSchema
,
value
);
},
[
&
](
List
<
JsonValue
>::
Reader
array
)
{
decodeArray
(
array
,
output
.
init
(
*
fieldSchema
,
array
.
size
()).
as
<
DynamicList
>
());
},
[
&
](
List
<
JsonValue
::
Field
>::
Reader
object
)
{
decodeObject
(
object
,
output
.
init
(
*
fieldSchema
).
as
<
DynamicStruct
>
());
});
}
else
{
// Unknown json fields are ignored to allow schema evolution
}
}
}
void
JsonCodec
::
decode
(
JsonValue
::
Reader
input
,
DynamicStruct
::
Builder
output
)
const
{
KJ_FAIL_ASSERT
(
"JSON decode not implement yet. :("
);
// TODO(soon): type and field handlers
switch
(
input
.
which
())
{
case
JsonValue
:
:
OBJECT
:
decodeObject
(
input
.
getObject
(),
output
);
break
;
default
:
KJ_FAIL_REQUIRE
(
"Top level json value must be object"
);
};
}
Orphan
<
DynamicValue
>
JsonCodec
::
decode
(
JsonValue
::
Reader
input
,
Type
type
,
Orphanage
orphanage
)
const
{
KJ_FAIL_ASSERT
(
"JSON decode not implement yet. :("
);
// TODO(soon)
KJ_FAIL_ASSERT
(
"JSON decode into orphanage not implement yet. :("
);
}
// -----------------------------------------------------------------------------
...
...
@@ -470,7 +671,7 @@ public:
return
kj
::
arrayPtr
(
originalPos
,
wrapped
.
begin
());
}
void
consumeWhitespace
()
{
consumeWhile
([](
char
chr
)
{
return
(
...
...
c++/src/capnp/compat/json.h
View file @
d5e04e32
...
...
@@ -201,6 +201,8 @@ private:
void
encodeField
(
StructSchema
::
Field
field
,
DynamicValue
::
Reader
input
,
JsonValue
::
Builder
output
)
const
;
void
decodeArray
(
List
<
JsonValue
>::
Reader
input
,
DynamicList
::
Builder
output
)
const
;
void
decodeObject
(
List
<
JsonValue
::
Field
>::
Reader
input
,
DynamicStruct
::
Builder
output
)
const
;
void
addTypeHandlerImpl
(
Type
type
,
HandlerBase
&
handler
);
void
addFieldHandlerImpl
(
StructSchema
::
Field
field
,
Type
type
,
HandlerBase
&
handler
);
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment