13 Nov 2018
Recommendations for how Conjure serialization and deserialization should treat duplicate keys in maps and sets.
When serializing or deserializing Conjure set
or map
keys, duplicate set items / map keys are not allowed.
Client must never send these, and it's recommended that servers reject them.
Some Conjure values have multiple equivalent representations, therefore we need to define equality carefully. This RFC proposes an equivalence relation that languages should adhere to.
The equivalence function is defined as such:
eq(a, b)
compares two JSON values of the same de-aliased Conjure type, returning true or false
It's helpful to define a couple of other functions in terms of conjure types:
fields(obj: conjure object) -> list<string>
returns a list of the object's fields.keys(map: map<K, V>) -> list<K>
returns a list of the map's keys.length(col: collection<T>) -> integer
returns the length of the collection (which may belist
orset
).obj.field
returns the field namedfield
of that objectmap[k]
returns the value at fieldk
if it exists in the map, ornull
is there is no such value.collection[i]
(where collection isset
orlist
) returns the item at positioni
(0..length(collection))
If not mentioned below, eq
for a conjure type is the result of a comparison on the raw JSON values, depending
on the JSON type.
Conjure type | Compared as |
---|---|
any |
?? |
bearertoken |
[string_eq][] |
binary |
? |
boolean |
[boolean_eq][] |
datetime |
[datetime_eq][] |
double |
[float_eq][] |
integer |
[integer_eq][] |
rid |
[string_eq][] |
safelong |
[integer_eq][] |
string |
[string_eq][] |
uuid |
[string_eq][] |
Enum | |
Object | |
Union | |
list<T> |
|
set<T> |
|
map<K, V> |
|
optional<T> |
string_eq(a, b)
returns true iff the unicode code point representations of a
and b
are the same.
Therefore, string_eq("\x102", "2")
should be true
.
integer_eq(a, b)
for integer values should compare the numbers according to their byte representations as 32-bit or 64-bit numbers.
This is safe since integer values and byte representations form a bijective relation.
eq(a, b)
for safelong values should compare the numbers according to their byte representations.
This is safe since long values and byte representations form a bijective relation.
eq(obj1, obj2) = {
for field in fields(obj1) {
let result = eq(obj1[field], obj2[field])
match result {
true => continue
false => return false
}
}
}
value(u) = u[u.type]
eq(u1, u2) = {
let result = eq(u1.type, u2.type)
match result {
true => eq(value(u1), value(u2))
false => return false
}
}
For two sets a
and b
, eq(a, b)
is true if:
a
andb
contain the same number of elements- there exists an ordering of
b
such thateq(a[i], b[i])
for everyi
between0
andlength(a)
(exclusive) As a consequence of the proposal (set items must be distinct), we also know thateq(a[i], b[j])
should be false for anyi != j
.
compare(m1, m2) = TODO same as object
The canonical JSON format of a double must conform to these constraints:
- Non-scientific notation must be used
- At least one decimal point must be used, even if it is
.0
- No superfluous trailing
0
decimals outside of the above case
Examples:
JSON representation | Canonical representation |
---|---|
-0 |
-0.0 |
0 |
0.0 |
1 |
1.0 |
1.00000 |
1.0 |
"1e1" |
10.0 |
1.2345678 |
1.2345678 |
1.23456780 |
1.2345678 |
"NaN" |
"NaN" |
"Infinity" |
"Infinity" |
"-Infinity" |
"-Infinity" |
Below is a table outlining the relative order of representative double values.
compare(a, b)
is LT iff a
appears higher than b
in the table, EQ if they are equal, GT otherwise.
Canonical representation |
---|
"-Infinity" |
... |
-0.0 |
0.0 |
... |
"Infinity" |
"NaN" |
The canonical JSON format of a datetime is a string formatted according to YYYY-MM-DDTHH:mm:ss.SSS±hh:mm
, in accordance with ISO 8601.
Examples:
JSON representation | Canonical representation |
---|---|
"2018-07-19T08:11:21Z" |
"2018-07-19T08:11:21.000+00:00" |
"2018-07-19T08:11:21+00:00" |
"2018-07-19T08:11:21.000+00:00" |
"2018-07-19T08:11:21-00:00" |
"2018-07-19T08:11:21.000+00:00" |
"2018-07-19T08:11:21.123-00:00" |
"2018-07-19T08:11:21.123+00:00" |
"20180719T081121Z" |
"2018-07-19T08:11:21.000+00:00" |
"2018-07-19T05:11:21+03:00" |
"2018-07-19T05:11:21.000+03:00" |
Canonical datetimes are ordered the same as strings.