diff --git a/docs/content/manual/dev/manual.yml b/docs/content/manual/dev/manual.yml index 38b8c5bfbe..3e72ad5455 100644 --- a/docs/content/manual/dev/manual.yml +++ b/docs/content/manual/dev/manual.yml @@ -1476,6 +1476,18 @@ sections: input: '[1, "1"]' output: ['1', '1'] + - title: "`toboolean`" + body: | + + The `toboolean` function parses its input as a boolean. It + will convert correctly-formatted strings to their boolean + equivalent, leave booleans alone, and give an error on all other input. + + examples: + - program: '.[] | toboolean' + input: '["true", "false", true, false]' + output: ['true', 'false', 'true', 'false'] + - title: "`tostring`" body: | diff --git a/jq.1.prebuilt b/jq.1.prebuilt index fadad46cc5..3f473b05d4 100644 --- a/jq.1.prebuilt +++ b/jq.1.prebuilt @@ -1556,6 +1556,21 @@ jq \'\.[] | tonumber\' . .IP "" 0 . +.SS "toboolean" +The \fBtoboolean\fR function parses its input as a boolean\. It will convert correctly\-formatted strings to their boolean equivalent, leave booleans alone, and give an error on all other input\. +. +.IP "" 4 +. +.nf + +jq \'\.[] | toboolean\' + ["true", "false", true, false] +=> true, false, true, false +. +.fi +. +.IP "" 0 +. .SS "tostring" The \fBtostring\fR function prints its input as a string\. Strings are left unchanged, and all other values are JSON\-encoded\. . diff --git a/src/builtin.c b/src/builtin.c index 717a07528a..875a5b5cf3 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -486,6 +486,23 @@ static jv f_tonumber(jq_state *jq, jv input) { return type_error(input, "cannot be parsed as a number"); } +static jv f_toboolean(jq_state *jq, jv input) { + if (jv_get_kind(input) == JV_KIND_TRUE || jv_get_kind(input) == JV_KIND_FALSE) { + return input; + } + if (jv_get_kind(input) == JV_KIND_STRING) { + const char *s = jv_string_value(input); + if (strcmp(s, "true") == 0) { + jv_free(input); + return jv_true(); + } else if (strcmp(s, "false") == 0) { + jv_free(input); + return jv_false(); + } + } + return type_error(input, "cannot be parsed as a boolean"); +} + static jv f_length(jq_state *jq, jv input) { if (jv_get_kind(input) == JV_KIND_ARRAY) { return jv_number(jv_array_length(input)); @@ -1850,6 +1867,7 @@ BINOPS CFUNC(f_dump, "tojson", 1), CFUNC(f_json_parse, "fromjson", 1), CFUNC(f_tonumber, "tonumber", 1), + CFUNC(f_toboolean, "toboolean", 1), CFUNC(f_tostring, "tostring", 1), CFUNC(f_keys, "keys", 1), CFUNC(f_keys_unsorted, "keys_unsorted", 1), diff --git a/tests/jq.test b/tests/jq.test index b9b1f8d2c4..287490f3b8 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -638,6 +638,21 @@ null 4 15 +map(toboolean) +["false","true",false,true] +[false,true,false,true] + +.[] | try toboolean catch . +[null,0,"tru","truee","fals","falsee",[],{}] +"null (null) cannot be parsed as a boolean" +"number (0) cannot be parsed as a boolean" +"string (\"tru\") cannot be parsed as a boolean" +"string (\"truee\") cannot be parsed as a boolean" +"string (\"fals\") cannot be parsed as a boolean" +"string (\"falsee\") cannot be parsed as a boolean" +"array ([]) cannot be parsed as a boolean" +"object ({}) cannot be parsed as a boolean" + [{"a":42},.object,10,.num,false,true,null,"b",[1,4]] | .[] as $x | [$x == .[]] {"object": {"a":42}, "num":10.0} [true, true, false, false, false, false, false, false, false] diff --git a/tests/man.test b/tests/man.test index 5489c5e20e..fb9ba8b0e5 100644 --- a/tests/man.test +++ b/tests/man.test @@ -440,6 +440,13 @@ sqrt 1 1 +.[] | toboolean +["true", "false", true, false] +true +false +true +false + .[] | tostring [1, "1", [1]] "1"