Skip to content

Commit 1cefde7

Browse files
authored
Add ability to refer to subfields of objects via dot notation in string formatting (#1011)
* added ability to refer to subfields of objects via dot notation in string formatting, e.g. "%(a.b)s" % {a:{b:"hello world"}}
1 parent f9b4c3a commit 1cefde7

4 files changed

+42
-4
lines changed

stdlib/std.jsonnet

+17-4
Original file line numberDiff line numberDiff line change
@@ -770,11 +770,24 @@ limitations under the License.
770770
error 'Cannot use * precision with object.'
771771
else
772772
code.prec;
773-
local val =
774-
if std.objectHasAll(obj, f) then
775-
obj[f]
773+
local get_nested_val(obj, f, start=0, end=0) =
774+
if !std.isObject(obj) then
775+
error 'Subfield ' + f[:start] + ' didn\'t yield an object.'
776+
else if end >= std.length(f) then
777+
if std.objectHasAll(obj, f[start:]) then
778+
obj[f[start:]]
779+
else
780+
error 'No such field: ' + f
781+
else if f[end] == "." then
782+
local key = f[start:end];
783+
if std.objectHasAll(obj, key) then
784+
get_nested_val(obj[key], f, end+1, end+1) tailstrict
785+
else
786+
error 'No such partial field: ' + f[:end]
776787
else
777-
error 'No such field: ' + f;
788+
get_nested_val(obj, f, start, end+1) tailstrict
789+
;
790+
local val = get_nested_val(obj, f);
778791
local s =
779792
if code.ctype == '%' then
780793
'%'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"%(a.b.c)s" % {a: {c: "hello"}}
2+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
RUNTIME ERROR: No such partial field: a.b
2+
std.jsonnet:<stdlib_position_redacted> function <get_nested_val>
3+
std.jsonnet:<stdlib_position_redacted> function <get_nested_val>
4+
std.jsonnet:<stdlib_position_redacted> thunk <val>
5+
std.jsonnet:<stdlib_position_redacted> thunk <val>
6+
std.jsonnet:<stdlib_position_redacted> thunk <a>
7+
std.jsonnet:<stdlib_position_redacted>
8+
std.jsonnet:<stdlib_position_redacted> thunk <a>
9+
std.jsonnet:<stdlib_position_redacted> function <anonymous>
10+
std.jsonnet:<stdlib_position_redacted> function <anonymous>
11+
std.jsonnet:<stdlib_position_redacted> function <format_code>
12+
...
13+
std.jsonnet:<stdlib_position_redacted> function <aux>
14+
std.jsonnet:<stdlib_position_redacted> function <padding>
15+
std.jsonnet:<stdlib_position_redacted> function <pad_left>
16+
std.jsonnet:<stdlib_position_redacted> thunk <s_padded>
17+
std.jsonnet:<stdlib_position_redacted> thunk <v>
18+
std.jsonnet:<stdlib_position_redacted> function <format_codes_obj>
19+
std.jsonnet:<stdlib_position_redacted> function <format_codes_obj>
20+
std.jsonnet:<stdlib_position_redacted> function <anonymous>
21+
std.jsonnet:<stdlib_position_redacted> function <anonymous>
22+
error.format.invalid_object_subfield.jsonnet:1:1-32

test_suite/format.jsonnet

+1
Original file line numberDiff line numberDiff line change
@@ -312,5 +312,6 @@ local text = |||
312312

313313
std.assertEqual(std.length(text), 1244) &&
314314

315+
std.assertEqual(std.format('%(a.b.c.d)s %(b.c)s', {a:{b:{c:{d:'hello'}}}, b:{c:'goodbye'}}), 'hello goodbye') &&
315316

316317
true

0 commit comments

Comments
 (0)