aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/json.cxx16
-rw-r--r--libbuild2/json.hxx18
-rw-r--r--libbuild2/variable.hxx6
-rw-r--r--tests/type/json/testscript2
4 files changed, 27 insertions, 15 deletions
diff --git a/libbuild2/json.cxx b/libbuild2/json.cxx
index 6295b59..4ed1631 100644
--- a/libbuild2/json.cxx
+++ b/libbuild2/json.cxx
@@ -511,7 +511,7 @@ namespace build2
}
void json_value::
- append (json_value&& v)
+ append (json_value&& v, bool override)
{
if (type == json_type::null)
{
@@ -584,10 +584,10 @@ namespace build2
{
return m.name == o.name;
}));
- if (i != object.end ())
- i->value = move (m.value);
- else
+ if (i == object.end ())
object.push_back (move (m));
+ else if (override)
+ i->value = move (m.value);
}
}
@@ -602,7 +602,7 @@ namespace build2
}
void json_value::
- prepend (json_value&& v)
+ prepend (json_value&& v, bool override)
{
if (type == json_type::null)
{
@@ -675,10 +675,10 @@ namespace build2
{
return m.name == o.name;
}));
- if (i != object.end ())
- i->value = move (m.value);
- else
+ if (i == object.end ())
object.insert (object.begin (), move (m));
+ else if (override)
+ i->value = move (m.value);
}
}
diff --git a/libbuild2/json.hxx b/libbuild2/json.hxx
index 538c87d..96596e3 100644
--- a/libbuild2/json.hxx
+++ b/libbuild2/json.hxx
@@ -170,16 +170,22 @@ namespace build2
// values are incompatible. Note that for numbers this can also lead to
// the change of the value type.
//
- // Append/prepend to an object overrides existing members. Append/prepend
- // an array to an array splices in the array elements rather than adding
- // an element of the array type.
+ // Append/prepend an array to an array splices in the array elements
+ // rather than adding an element of the array type.
+ //
+ // By default, append to an object overrides existing members while
+ // prepend does not. In a sense, whatever appears last is kept, which is
+ // consistent with what we expect to happen when specifying the same name
+ // repeatedly (provided it's not considered invalid) in a text
+ // representation (e.g., {"a":1,"a":2}). Position-wise, both append and
+ // prepend retain the positions of existing members with append inserting
+ // new ones at the end while prepend -- at the beginning.
//
void
- append (json_value&&);
+ append (json_value&&, bool override = true);
void
- prepend (json_value&&);
-
+ prepend (json_value&&, bool override = false);
// Array element access.
//
diff --git a/libbuild2/variable.hxx b/libbuild2/variable.hxx
index b157806..d754edf 100644
--- a/libbuild2/variable.hxx
+++ b/libbuild2/variable.hxx
@@ -1237,6 +1237,12 @@ namespace build2
// of what looks like harmless looseness in a few contexts (such as the
// $json.member_*() functions).
//
+ // Note that similar to map, JSON object append/+= is overriding while
+ // prepend/=+ is not. In a sense, whatever appears last (from left to right)
+ // is kept, which is consistent with what we expect to happen when
+ // specifying the same name repeatedly (provided it's not considered
+ // invalid) in a representation (e.g., {"a":1,"a":2}).
+ //
template <>
struct LIBBUILD2_SYMEXPORT value_traits<json_value>
{
diff --git a/tests/type/json/testscript b/tests/type/json/testscript
index 5295fbc..0e9af95 100644
--- a/tests/type/json/testscript
+++ b/tests/type/json/testscript
@@ -204,7 +204,7 @@
: object
:
- $* <<EOI >'{"zero":0,"one":6,"two":8,"three":9,"four":4,"five":5,"seven":7}'
+ $* <<EOI >'{"zero":0,"one":6,"two":8,"three":3,"four":4,"five":5,"seven":7}'
o = [json] one@1 two@2 three@3
o += four@4
o += five@5 one@6