1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 03:56:01 +01:00
This commit is contained in:
Farid Zakaria 2025-11-06 13:07:50 -08:00 committed by GitHub
commit 74219794ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 107 additions and 6 deletions

View file

@ -12,6 +12,13 @@ struct Value;
MakeError(JSONParseError, Error); MakeError(JSONParseError, Error);
void parseJSON(EvalState & state, const std::string_view & s, Value & v); /**
* Parse the string into the Value
* @param state
* @param s
* @param v
* @param allowComments Whether to allow comments in the JSON
*/
void parseJSON(EvalState & state, const std::string_view & s, Value & v, bool allowComments = false);
} // namespace nix } // namespace nix

View file

@ -201,10 +201,11 @@ public:
} }
}; };
void parseJSON(EvalState & state, const std::string_view & s_, Value & v) void parseJSON(EvalState & state, const std::string_view & s_, Value & v, bool allowComments)
{ {
JSONSax parser(state, v); JSONSax parser(state, v);
bool res = json::sax_parse(s_, &parser); bool res = json::sax_parse(
s_, &parser, nlohmann::detail::input_format_t::json, /* strict= */ true, /* ignore_comments= */ allowComments);
if (!res) if (!res)
throw JSONParseError("Invalid JSON Value"); throw JSONParseError("Invalid JSON Value");
} }

View file

@ -2539,11 +2539,11 @@ static RegisterPrimOp primop_toJSON({
}); });
/* Parse a JSON string to a value. */ /* Parse a JSON string to a value. */
static void prim_fromJSON(EvalState & state, const PosIdx pos, Value ** args, Value & v) static void prim_fromJSON(EvalState & state, const PosIdx pos, Value ** args, Value & v, bool allow_comments)
{ {
auto s = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.fromJSON"); auto s = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.fromJSON");
try { try {
parseJSON(state, s, v); parseJSON(state, s, v, allow_comments);
} catch (JSONParseError & e) { } catch (JSONParseError & e) {
e.addTrace(state.positions[pos], "while decoding a JSON string"); e.addTrace(state.positions[pos], "while decoding a JSON string");
throw; throw;
@ -2562,7 +2562,38 @@ static RegisterPrimOp primop_fromJSON({
returns the value `{ x = [ 1 2 3 ]; y = null; }`. returns the value `{ x = [ 1 2 3 ]; y = null; }`.
)", )",
.fun = prim_fromJSON, .fun =
[](EvalState & state, const PosIdx pos, Value ** args, Value & v) {
return prim_fromJSON(state, pos, args, v, false);
},
});
static RegisterPrimOp primop_fromJSONC({
.name = "__fromJSONC",
.args = {"e"},
.doc = R"(
Convert a JSON string, potentially with comments, to a Nix value.
For example,
```nix
builtins.fromJSONC ''
{
// This is a comment
"x": [1, 2, 3],
/* This is another comment */
"y": null
}
''
```
returns the value `{ x = [ 1 2 3 ]; y = null; }`.
This function supports JSON with comments.
)",
.fun =
[](EvalState & state, const PosIdx pos, Value ** args, Value & v) {
return prim_fromJSON(state, pos, args, v, true);
},
}); });
/* Store a string in the Nix store as a source file that can be used /* Store a string in the Nix store as a source file that can be used

View file

@ -0,0 +1 @@
true

View file

@ -0,0 +1,61 @@
builtins.fromJSONC ''
{
// This is a comment
"Video": {
/* Multi line comment single line */
"Title": "The Penguin Chronicles",
"Width": 1920,
"Height": 1080,
/**
* Multi line comment
* with multiple lines
*/
"EmbeddedData": [3.14159, 23493,null, true ,false, -10],
"Thumb": {
"Url": "http://www.example.com/video/5678931",
"Width": 200,
"Height": 250
},
"Animated" : false,
"IDs": [116, 943, 234, 38793, true ,false,null, -100],
"Escapes": "\"\\\/\t\n\r\t",
"Subtitle" : false,
"Latitude": 37.7668,
"Longitude": -122.3959
}
}
'' == {
Video = {
Title = "The Penguin Chronicles";
Width = 1920;
Height = 1080;
EmbeddedData = [
3.14159
23493
null
true
false
(0 - 10)
];
Thumb = {
Url = "http://www.example.com/video/5678931";
Width = 200;
Height = 250;
};
Animated = false;
IDs = [
116
943
234
38793
true
false
null
(0 - 100)
];
Escapes = "\"\\\/\t\n\r\t"; # supported in JSON but not Nix: \b\f
Subtitle = false;
Latitude = 37.7668;
Longitude = -122.3959;
};
}