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
9aa52315
Commit
9aa52315
authored
Mar 23, 2016
by
Branislav Katreniak
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
json: implement decode(... input, DynamicStruct::Builder output)
parent
c242a3a0
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
187 additions
and
2 deletions
+187
-2
json-test.c++
c++/src/capnp/compat/json-test.c++
+77
-0
json.c++
c++/src/capnp/compat/json.c++
+108
-2
json.h
c++/src/capnp/compat/json.h
+2
-0
No files found.
c++/src/capnp/compat/json-test.c++
View file @
9aa52315
...
...
@@ -183,6 +183,83 @@ 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 decodedMessage; \
auto root = decodedMessage.initRoot<TestAllTypes>(); \
json.decode(s, root); \
KJ_EXPECT((f)) \
}
CASE
(
R"({})"
,
root
.
getBoolField
()
==
false
);
CASE
(
R"({"unknownField":7})"
,
root
.
getBoolField
()
==
false
);
CASE
(
R"({"boolField":null})"
,
root
.
getBoolField
()
==
false
);
CASE
(
R"({"boolField":true})"
,
root
.
getBoolField
()
==
true
);
CASE
(
R"({"int8Field":7})"
,
root
.
getInt8Field
()
==
7
);
CASE
(
R"({"int8Field":"7"})"
,
root
.
getInt8Field
()
==
7
);
CASE
(
R"({"int16Field":7})"
,
root
.
getInt16Field
()
==
7
);
CASE
(
R"({"int16Field":"7"})"
,
root
.
getInt16Field
()
==
7
);
CASE
(
R"({"int32Field":7})"
,
root
.
getInt32Field
()
==
7
);
CASE
(
R"({"int32Field":"7"})"
,
root
.
getInt32Field
()
==
7
);
CASE
(
R"({"int64Field":7})"
,
root
.
getInt64Field
()
==
7
);
CASE
(
R"({"int64Field":"7"})"
,
root
.
getInt64Field
()
==
7
);
CASE
(
R"({"uInt8Field":7})"
,
root
.
getUInt8Field
()
==
7
);
CASE
(
R"({"uInt8Field":"7"})"
,
root
.
getUInt8Field
()
==
7
);
CASE
(
R"({"uInt16Field":7})"
,
root
.
getUInt16Field
()
==
7
);
CASE
(
R"({"uInt16Field":"7"})"
,
root
.
getUInt16Field
()
==
7
);
CASE
(
R"({"uInt32Field":7})"
,
root
.
getUInt32Field
()
==
7
);
CASE
(
R"({"uInt32Field":"7"})"
,
root
.
getUInt32Field
()
==
7
);
CASE
(
R"({"uInt64Field":7})"
,
root
.
getUInt64Field
()
==
7
);
CASE
(
R"({"uInt64Field":"7"})"
,
root
.
getUInt64Field
()
==
7
);
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
(
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":[null]})"
,
root
.
getBoolList
().
size
()
==
1
);
CASE
(
R"({"boolList":[null]})"
,
root
.
getBoolList
()[
0
]
==
false
);
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"({"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
}
KJ_TEST
(
"basic json decoding"
)
{
// TODO(cleanup): this test is a mess!
JsonCodec
json
;
...
...
c++/src/capnp/compat/json.c++
View file @
9aa52315
...
...
@@ -379,13 +379,119 @@ 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
()
&&
errno
!=
ERANGE
,
"String is not correct int64 number"
);
return
value
;
}
uint64_t
parseUInt64
(
kj
::
StringPtr
s
)
{
char
*
endPtr
;
errno
=
0
;
uint64_t
value
=
std
::
strtoull
(
s
.
begin
(),
&
endPtr
,
10
);
KJ_ASSERT
(
endPtr
==
s
.
end
()
&&
errno
!=
ERANGE
,
"String is not correct uint64 number"
);
return
value
;
}
template
<
typename
Set
,
typename
DecodeArray
,
typename
DecodeObject
>
void
decodeField
(
Type
type
,
JsonValue
::
Reader
value
,
Set
set
,
DecodeArray
decodeArray
,
DecodeObject
decodeObject
)
{
switch
(
value
.
which
())
{
case
JsonValue
:
:
NULL_
:
break
;
case
JsonValue
:
:
BOOLEAN
:
set
(
value
.
getBoolean
());
break
;
case
JsonValue
:
:
NUMBER
:
set
(
value
.
getNumber
());
break
;
case
JsonValue
:
:
STRING
:
if
(
type
.
isInt8
()
||
type
.
isInt16
()
||
type
.
isInt32
()
||
type
.
isInt64
())
{
set
(
parseInt64
(
value
.
getString
()));
}
else
if
(
type
.
isUInt8
()
||
type
.
isUInt16
()
||
type
.
isUInt32
()
||
type
.
isUInt64
())
{
set
(
parseUInt64
(
value
.
getString
()));
}
else
{
set
(
value
.
getString
());
}
break
;
case
JsonValue
:
:
ARRAY
:
{
if
(
type
.
isData
())
{
kj
::
Vector
<
byte
>
data
;
for
(
auto
arrayObject
:
value
.
getArray
())
{
auto
x
=
int
(
arrayObject
.
getNumber
());
KJ_REQUIRE
(
x
>=
0
&&
x
<=
255
,
"Number in array of bytes out of range."
);
data
.
add
(
byte
(
x
));
}
set
(
Data
::
Reader
(
data
.
asPtr
()));
}
else
{
decodeArray
(
value
.
getArray
());
}
break
;
}
case
JsonValue
:
:
OBJECT
:
decodeObject
(
value
.
getObject
());
break
;
case
JsonValue
:
:
CALL
:
//TODO(soon)
KJ_FAIL_ASSERT
(
"JSON call decode not implemented yet. :("
);
break
;
}
}
}
//namespace
void
JsonCodec
::
decodeArray
(
List
<
JsonValue
>::
Reader
input
,
DynamicList
::
Builder
output
)
const
{
KJ_ASSERT
(
input
.
size
()
==
output
.
size
(),
"Builder must be 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. :("
);
}
// -----------------------------------------------------------------------------
...
...
c++/src/capnp/compat/json.h
View file @
9aa52315
...
...
@@ -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