mirror of
https://github.com/zeek/zeek.git
synced 2025-10-08 17:48:21 +00:00
Support table deserialization in from_json()
This allows additional data roundtripping through JSON since to_json() already supports tables. There are some subtleties around the formatting of strings in JSON object keys, for which this adds a bit of helper infrastructure. This also expands the language.table test to verify the roundtrips, and adapts bif.from_json to include a table in the test record.
This commit is contained in:
parent
df645e9bb2
commit
92c1098e97
6 changed files with 148 additions and 64 deletions
83
src/Val.cc
83
src/Val.cc
|
@ -330,7 +330,7 @@ TableValPtr Val::GetRecordFields() {
|
|||
}
|
||||
|
||||
// A predicate to identify those types we render as a string in JSON.
|
||||
static bool IsQuotedJSONType(const TypePtr& t) {
|
||||
static bool UsesJSONStringType(const TypePtr& t) {
|
||||
if ( t == nullptr )
|
||||
return false;
|
||||
|
||||
|
@ -440,8 +440,10 @@ static void BuildJSON(json::detail::NullDoubleWriter& writer, Val* val, bool onl
|
|||
BuildJSON(key_writer, entry_key, only_loggable, re);
|
||||
string key_str = buffer.GetString();
|
||||
|
||||
if ( key_str.length() >= 2 && key_str[0] == '"' && key_str[key_str.length() - 1] == '"' )
|
||||
// Strip quotes.
|
||||
// Strip the quotes for any type we render as a string. This
|
||||
// makes the JSON object's keys look more natural, yielding
|
||||
// '{ "foo": ... }', not '{ "\"foo\"": ... }', for such types.
|
||||
if ( UsesJSONStringType(entry_key->GetType()) )
|
||||
key_str = key_str.substr(1, key_str.length() - 2);
|
||||
|
||||
BuildJSON(writer, entry->GetVal().get(), only_loggable, re, key_str);
|
||||
|
@ -1064,34 +1066,69 @@ static std::variant<ValPtr, std::string> BuildVal(const rapidjson::Value& j, con
|
|||
}
|
||||
|
||||
case TYPE_TABLE: {
|
||||
if ( ! j.IsArray() )
|
||||
return mismatch_err();
|
||||
|
||||
if ( ! t->IsSet() )
|
||||
return util::fmt("tables are not supported");
|
||||
|
||||
auto tt = t->AsSetType();
|
||||
auto tl = tt->GetIndices();
|
||||
auto tt = t->AsTableType(); // The table vs set type does not matter below
|
||||
auto tv = make_intrusive<TableVal>(IntrusivePtr{NewRef{}, tt});
|
||||
auto tl = tt->GetIndices();
|
||||
|
||||
for ( const auto& item : j.GetArray() ) {
|
||||
std::variant<ValPtr, std::string> v;
|
||||
if ( t->IsSet() ) {
|
||||
if ( ! j.IsArray() )
|
||||
return mismatch_err();
|
||||
|
||||
if ( tl->GetTypes().size() == 1 )
|
||||
v = BuildVal(item, tl->GetPureType(), key_func);
|
||||
else
|
||||
v = BuildVal(item, tl, key_func);
|
||||
for ( const auto& item : j.GetArray() ) {
|
||||
std::variant<ValPtr, std::string> v;
|
||||
|
||||
if ( ! get_if<ValPtr>(&v) )
|
||||
return v;
|
||||
if ( tl->GetTypes().size() == 1 )
|
||||
v = BuildVal(item, tl->GetPureType(), key_func);
|
||||
else
|
||||
v = BuildVal(item, tl, key_func);
|
||||
|
||||
if ( ! std::get<ValPtr>(v) )
|
||||
continue;
|
||||
if ( ! get_if<ValPtr>(&v) )
|
||||
return v;
|
||||
if ( ! std::get<ValPtr>(v) )
|
||||
continue;
|
||||
|
||||
tv->Assign(std::move(std::get<ValPtr>(v)), nullptr);
|
||||
tv->Assign(std::move(std::get<ValPtr>(v)), nullptr);
|
||||
}
|
||||
|
||||
return tv;
|
||||
}
|
||||
else {
|
||||
if ( ! j.IsObject() )
|
||||
return mismatch_err();
|
||||
|
||||
return tv;
|
||||
for ( auto it = j.MemberBegin(); it != j.MemberEnd(); ++it ) {
|
||||
rapidjson::Document idxstr;
|
||||
idxstr.Parse(it->name.GetString(), it->name.GetStringLength());
|
||||
|
||||
std::variant<ValPtr, std::string> idx;
|
||||
|
||||
if ( tl->GetTypes().size() > 1 )
|
||||
idx = BuildVal(idxstr, tl, key_func);
|
||||
else if ( UsesJSONStringType(tl->GetPureType()) )
|
||||
// Parse this with the quotes the string came with. This
|
||||
// mirrors the quote-stripping in BuildJSON().
|
||||
idx = BuildVal(it->name, tl->GetPureType(), key_func);
|
||||
else
|
||||
// Parse the string's content, not the full JSON string.
|
||||
idx = BuildVal(idxstr, tl->GetPureType(), key_func);
|
||||
|
||||
if ( ! get_if<ValPtr>(&idx) )
|
||||
return idx;
|
||||
if ( ! std::get<ValPtr>(idx) )
|
||||
continue;
|
||||
|
||||
auto v = BuildVal(it->value, tt->Yield(), key_func);
|
||||
|
||||
if ( ! get_if<ValPtr>(&v) )
|
||||
return v;
|
||||
if ( ! std::get<ValPtr>(v) )
|
||||
continue;
|
||||
|
||||
tv->Assign(std::move(std::get<ValPtr>(idx)), std::move(std::get<ValPtr>(v)));
|
||||
}
|
||||
|
||||
return tv;
|
||||
}
|
||||
}
|
||||
|
||||
case TYPE_RECORD: {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue