daml_json/
value_encode.rs

1use crate::error::DamlJsonCodecResult;
2use crate::util::Required;
3use bigdecimal::ToPrimitive;
4use chrono::SecondsFormat;
5use daml_grpc::data::value::{DamlRecord, DamlValue};
6use serde_json::{json, Value};
7use std::collections::HashMap;
8
9/// Encode a `DamlValue` as JSON.
10#[derive(Debug, Default)]
11pub struct JsonValueEncoder {
12    encode_decimal_as_string: bool,
13    encode_int64_as_string: bool,
14}
15
16impl JsonValueEncoder {
17    pub const fn new(encode_decimal_as_string: bool, encode_int64_as_string: bool) -> Self {
18        Self {
19            encode_decimal_as_string,
20            encode_int64_as_string,
21        }
22    }
23
24    /// Encode a GRPC `DamlValue` as JSON `Value`.
25    pub fn encode_value(&self, value: &DamlValue) -> DamlJsonCodecResult<Value> {
26        self.do_encode_value(value, true)
27    }
28
29    /// Encode a GRPC `DamlRecord` as JSON `Value`.
30    pub fn encode_record(&self, record: &DamlRecord) -> DamlJsonCodecResult<Value> {
31        self.do_encode_record(record)
32    }
33
34    /// Recursively encode a `DamlValue` as a JSON `Value`.
35    ///
36    /// Here `top_level` refers to whether we are processing a value corresponding to the "top level" of a type or a
37    /// nested types.  This is required to support the "shortcut" encodings for optional fields.
38    ///
39    /// For example given a `DamlValue` of type `DamlOptional<DamlText>` the `DamlOptional` is not considered a nested
40    /// type and so `top_level` will be true whilst the contained `DamlText` is considered as a nested type and so
41    /// `top_level` will be false.
42    ///
43    /// Note that the `DamlValue` associated with each field of a `DamlRecord` is not considered nested and so will be
44    /// processed with `top_level` set to true.  If the field type contains nested data types (such as an optional)
45    /// then these will behave as described above.
46    ///
47    /// See the [Daml LF JSON Encoding documentation](https://docs.daml.com/json-api/lf-value-specification.html) for details.
48    fn do_encode_value(&self, value: &DamlValue, top_level: bool) -> DamlJsonCodecResult<Value> {
49        match value {
50            DamlValue::Unit => Ok(json!({})),
51            DamlValue::Bool(b) => Ok(json!(b)),
52            DamlValue::Int64(i) =>
53                if self.encode_int64_as_string {
54                    Ok(json!(format!("{}", i)))
55                } else {
56                    Ok(json!(i))
57                },
58            DamlValue::Numeric(n) =>
59                if self.encode_decimal_as_string {
60                    Ok(json!(format!("{}", n)))
61                } else {
62                    Ok(json!(n.to_f64().req()?))
63                },
64            DamlValue::Timestamp(timestamp) => Ok(json!(timestamp.to_rfc3339_opts(SecondsFormat::Millis, true))),
65            DamlValue::Date(date) => Ok(json!(date.naive_utc().to_string())),
66            DamlValue::Text(text) => Ok(json!(text)),
67            DamlValue::Party(party) => Ok(json!(party.party)),
68            DamlValue::ContractId(id) => Ok(json!(id.contract_id)),
69            DamlValue::Optional(opt) => match opt {
70                None if top_level => Ok(json!(null)),
71                None => Ok(json!([])),
72                Some(inner) if top_level => Ok(json!(self.do_encode_value(inner, false)?)),
73                Some(inner) => Ok(json!([self.do_encode_value(inner, false)?])),
74            },
75            DamlValue::Record(record) => self.do_encode_record(record),
76            DamlValue::List(list) => {
77                let items =
78                    list.iter().map(|i| self.do_encode_value(i, true)).collect::<DamlJsonCodecResult<Vec<_>>>()?;
79                Ok(json!(items))
80            },
81            DamlValue::Map(map) => {
82                let entries = map
83                    .iter()
84                    .map(|(k, v)| Ok((k.as_str(), self.do_encode_value(v, true)?)))
85                    .collect::<DamlJsonCodecResult<HashMap<_, _>>>()?;
86                Ok(json!(entries))
87            },
88            DamlValue::Variant(variant) => {
89                let ctor = variant.constructor();
90                let value = self.do_encode_value(variant.value(), true)?;
91                Ok(json!({"tag": ctor, "value": value}))
92            },
93            DamlValue::Enum(data_enum) => Ok(json!(data_enum.constructor())),
94            DamlValue::GenMap(map) => {
95                let entries = map
96                    .iter()
97                    .map(|(k, v)| Ok((self.do_encode_value(k, true)?, self.do_encode_value(v, true)?)))
98                    .collect::<DamlJsonCodecResult<Vec<(_, _)>>>()?;
99                Ok(json!(entries))
100            },
101        }
102    }
103
104    /// Recursively encode a `DamlRecord` as a JSON `Value`.
105    fn do_encode_record(&self, record: &DamlRecord) -> DamlJsonCodecResult<Value> {
106        let has_labels = record.fields().iter().all(|f| f.label().is_some());
107        if has_labels {
108            let fields = record
109                .fields()
110                .iter()
111                .filter(|f| !matches!(f.value(), DamlValue::Optional(None)))
112                .map(|f| Ok((f.label().as_ref().req()?, self.do_encode_value(f.value(), true)?)))
113                .collect::<DamlJsonCodecResult<HashMap<_, _>>>()?;
114            Ok(json!(fields))
115        } else {
116            let fields = record
117                .fields()
118                .iter()
119                .map(|f| self.do_encode_value(f.value(), true))
120                .collect::<DamlJsonCodecResult<Vec<_>>>()?;
121            Ok(json!(fields))
122        }
123    }
124}
125
126#[cfg(test)]
127mod tests {
128    use super::{DamlJsonCodecResult, DamlValue, JsonValueEncoder};
129    use crate::util::Required;
130    use crate::value_decode::JsonTryAsExt;
131    use daml::macros::daml_value;
132    use daml_grpc::data::value::{DamlEnum, DamlRecord, DamlRecordField};
133    use daml_grpc::data::DamlIdentifier;
134    use daml_grpc::primitive_types::DamlTextMap;
135    use maplit::hashmap;
136    use serde_json::{json, Value};
137
138    #[test]
139    fn test_unit() -> DamlJsonCodecResult<()> {
140        let grpc_value = daml_value!();
141        let expected = json!({});
142        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
143        assert_eq!(actual, expected);
144        Ok(())
145    }
146
147    #[test]
148    fn test_bool() -> DamlJsonCodecResult<()> {
149        let grpc_value = daml_value!(true);
150        let expected = json!(true);
151        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
152        assert_eq!(actual, expected);
153        Ok(())
154    }
155
156    #[test]
157    fn test_i64() -> DamlJsonCodecResult<()> {
158        let grpc_value = daml_value!(42);
159        let expected = json!(42);
160        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
161        assert_eq!(actual, expected);
162        Ok(())
163    }
164
165    #[test]
166    fn test_i64_neg() -> DamlJsonCodecResult<()> {
167        let grpc_value = daml_value!(-42);
168        let expected = json!(-42);
169        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
170        assert_eq!(actual, expected);
171        Ok(())
172    }
173
174    #[test]
175    fn test_i64_as_string() -> DamlJsonCodecResult<()> {
176        let grpc_value = daml_value!(42);
177        let expected = json!("42");
178        let actual = JsonValueEncoder::new(false, true).encode_value(&grpc_value)?;
179        assert_eq!(actual, expected);
180        Ok(())
181    }
182
183    #[test]
184    fn test_i64_neg_as_string() -> DamlJsonCodecResult<()> {
185        let grpc_value = daml_value!(-42);
186        let expected = json!("-42");
187        let actual = JsonValueEncoder::new(false, true).encode_value(&grpc_value)?;
188        assert_eq!(actual, expected);
189        Ok(())
190    }
191
192    #[test]
193    fn test_numeric() -> DamlJsonCodecResult<()> {
194        let grpc_value = daml_value!(1.0);
195        let expected = json!(1.0);
196        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
197        assert_eq!(actual, expected);
198        Ok(())
199    }
200
201    #[test]
202    fn test_numeric_neg() -> DamlJsonCodecResult<()> {
203        let grpc_value = daml_value!(-1.0);
204        let expected = json!(-1.0);
205        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
206        assert_eq!(actual, expected);
207        Ok(())
208    }
209
210    #[test]
211    fn test_numeric_as_string() -> DamlJsonCodecResult<()> {
212        let grpc_value = daml_value!(1.000_000_000_000_000);
213        let expected = json!("1.000000000000000");
214        let actual = JsonValueEncoder::new(true, false).encode_value(&grpc_value)?;
215        assert_eq!(actual, expected);
216        Ok(())
217    }
218
219    #[test]
220    fn test_numeric_neg_as_string() -> DamlJsonCodecResult<()> {
221        let grpc_value = daml_value!(-1.000_000_000_000_000);
222        let expected = json!("-1.000000000000000");
223        let actual = JsonValueEncoder::new(true, false).encode_value(&grpc_value)?;
224        assert_eq!(actual, expected);
225        Ok(())
226    }
227
228    #[test]
229    fn test_text() -> DamlJsonCodecResult<()> {
230        let grpc_value = daml_value!("test");
231        let expected = json!("test");
232        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
233        assert_eq!(actual, expected);
234        Ok(())
235    }
236
237    #[test]
238    fn test_text_empty() -> DamlJsonCodecResult<()> {
239        let grpc_value = daml_value!("");
240        let expected = json!("");
241        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
242        assert_eq!(actual, expected);
243        Ok(())
244    }
245
246    #[test]
247    fn test_date() -> DamlJsonCodecResult<()> {
248        let grpc_value = daml_value!("2019-06-18"::d);
249        let expected = json!("2019-06-18");
250        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
251        assert_eq!(actual, expected);
252        Ok(())
253    }
254
255    #[test]
256    fn test_date_min() -> DamlJsonCodecResult<()> {
257        let grpc_value = daml_value!("9999-12-31"::d);
258        let expected = json!("9999-12-31");
259        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
260        assert_eq!(actual, expected);
261        Ok(())
262    }
263
264    #[test]
265    fn test_date_max() -> DamlJsonCodecResult<()> {
266        let grpc_value = daml_value!("0001-01-01"::d);
267        let expected = json!("0001-01-01");
268        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
269        assert_eq!(actual, expected);
270        Ok(())
271    }
272
273    #[test]
274    fn test_timestamp_full() -> DamlJsonCodecResult<()> {
275        let grpc_value = daml_value!("1990-11-09T04:30:23.1234569Z"::t);
276        let expected = json!("1990-11-09T04:30:23.123Z");
277        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
278        assert_eq!(actual, expected);
279        Ok(())
280    }
281
282    #[test]
283    fn test_timestamp_no_sub_sec() -> DamlJsonCodecResult<()> {
284        let grpc_value = daml_value!("1990-11-09T04:30:23Z"::t);
285        let expected = json!("1990-11-09T04:30:23.000Z");
286        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
287        assert_eq!(actual, expected);
288        Ok(())
289    }
290
291    #[test]
292    fn test_timestamp_no_micros() -> DamlJsonCodecResult<()> {
293        let grpc_value = daml_value!("1990-11-09T04:30:23.123Z"::t);
294        let expected = json!("1990-11-09T04:30:23.123Z");
295        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
296        assert_eq!(actual, expected);
297        Ok(())
298    }
299
300    #[test]
301    fn test_timestamp_min() -> DamlJsonCodecResult<()> {
302        let grpc_value = daml_value!("0001-01-01T00:00:00Z"::t);
303        let expected = json!("0001-01-01T00:00:00.000Z");
304        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
305        assert_eq!(actual, expected);
306        Ok(())
307    }
308
309    #[test]
310    fn test_timestamp_max() -> DamlJsonCodecResult<()> {
311        let grpc_value = daml_value!("9999-12-31T23:59:59.999999Z"::t);
312        let expected = json!("9999-12-31T23:59:59.999Z");
313        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
314        assert_eq!(actual, expected);
315        Ok(())
316    }
317
318    #[test]
319    fn test_party() -> DamlJsonCodecResult<()> {
320        let grpc_value = daml_value!("Alice"::p);
321        let expected = json!("Alice");
322        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
323        assert_eq!(actual, expected);
324        Ok(())
325    }
326
327    #[test]
328    fn test_contract_id() -> DamlJsonCodecResult<()> {
329        let grpc_value = daml_value!("#0:0"::c);
330        let expected = json!("#0:0");
331        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
332        assert_eq!(actual, expected);
333        Ok(())
334    }
335
336    #[test]
337    fn test_opt_none() -> DamlJsonCodecResult<()> {
338        let grpc_value = daml_value!({?!});
339        let expected = json!(null);
340        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
341        assert_eq!(actual, expected);
342        Ok(())
343    }
344
345    #[test]
346    fn test_opt_int_some() -> DamlJsonCodecResult<()> {
347        let grpc_value = daml_value!({?=42});
348        let expected = json!(42);
349        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
350        assert_eq!(actual, expected);
351        Ok(())
352    }
353
354    #[test]
355    fn test_opt_opt_int_some_none() -> DamlJsonCodecResult<()> {
356        let grpc_value = daml_value!({?={?!}});
357        let expected = json!([]);
358        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
359        assert_eq!(actual, expected);
360        Ok(())
361    }
362
363    #[test]
364    fn test_opt_opt_int_some_some() -> DamlJsonCodecResult<()> {
365        let grpc_value = daml_value!({?={?=42}});
366        let expected = json!([42]);
367        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
368        assert_eq!(actual, expected);
369        Ok(())
370    }
371
372    #[test]
373    fn test_opt_opt_opt_int_some_some_none() -> DamlJsonCodecResult<()> {
374        let grpc_value = daml_value!({?={?={?!}}});
375        let expected = json!([[]]);
376        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
377        assert_eq!(actual, expected);
378        Ok(())
379    }
380
381    #[test]
382    fn test_opt_opt_opt_int_some_some_some() -> DamlJsonCodecResult<()> {
383        let grpc_value = daml_value!({?={?={?=42}}});
384        let expected = json!([[42]]);
385        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
386        assert_eq!(actual, expected);
387        Ok(())
388    }
389
390    #[test]
391    fn test_opt_opt_opt_opt_int_some_some_some_none() -> DamlJsonCodecResult<()> {
392        let grpc_value = daml_value!({?={?={?={?!}}}});
393        let expected = json!([[[]]]);
394        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
395        assert_eq!(actual, expected);
396        Ok(())
397    }
398
399    #[test]
400    fn test_opt_opt_opt_opt_text_some_some_some_some() -> DamlJsonCodecResult<()> {
401        let grpc_value = daml_value!({?={?={?={?="Test"}}}});
402        let expected = json!([[["Test"]]]);
403        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
404        assert_eq!(actual, expected);
405        Ok(())
406    }
407
408    #[test]
409    fn test_opt_unit_some() -> DamlJsonCodecResult<()> {
410        let grpc_value = daml_value!({?=()});
411        let expected = json!({});
412        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
413        assert_eq!(actual, expected);
414        Ok(())
415    }
416
417    #[test]
418    fn test_empty_record() -> DamlJsonCodecResult<()> {
419        let grpc_value = daml_value!({});
420        let expected = json!({});
421        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
422        assert_eq!(actual, expected);
423        Ok(())
424    }
425
426    #[test]
427    fn test_record() -> DamlJsonCodecResult<()> {
428        let grpc_value = daml_value!({landlord: "Alice"::p, tenant: "Bob"::p, terms: "test terms"});
429        let expected = json!({
430             "landlord": "Alice",
431             "tenant": "Bob",
432             "terms": "test terms",
433        });
434        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
435        assert_eq!(actual, expected);
436        Ok(())
437    }
438
439    #[test]
440    fn test_record_as_array() -> DamlJsonCodecResult<()> {
441        let grpc_value = DamlValue::new_record(DamlRecord::new(
442            vec![
443                DamlRecordField::new(None::<String>, DamlValue::new_party("Alice")),
444                DamlRecordField::new(None::<String>, DamlValue::new_party("Bob")),
445                DamlRecordField::new(None::<String>, DamlValue::new_text("test terms")),
446            ],
447            None::<DamlIdentifier>,
448        ));
449        let expected = json!(["Alice", "Bob", "test terms"]);
450        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
451        assert_eq!(actual, expected);
452        Ok(())
453    }
454
455    /// `Depth1 with foo: None : data Depth1 = Depth1 with foo: Optional Int64` -> `{ }`
456    ///
457    /// Note that we could equally encode this as `{ "foo": null }`, both decode to the same `DamlValue`.
458    #[test]
459    fn test_record_depth1_omitted_or_none() -> DamlJsonCodecResult<()> {
460        let grpc_value = daml_value!({foo: {?!}});
461        let expected = json!({});
462        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
463        assert_eq!(actual, expected);
464        Ok(())
465    }
466
467    /// `Depth1 with foo: Some 42 : data Depth1 = Depth1 with foo: Optional Int64` -> `{ foo: 42 }`
468    #[test]
469    fn test_record_depth1_some() -> DamlJsonCodecResult<()> {
470        let grpc_value = daml_value!({foo: {?=42}});
471        let expected = json!({ "foo": 42 });
472        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
473        assert_eq!(actual, expected);
474        Ok(())
475    }
476
477    /// `Depth2 with foo: None : data Depth2 = Depth2 with foo: Optional (Optional Int64)` -> `{ }`
478    ///
479    /// Note that we could equally encode this as `{ "foo": null }`, both decode to the same `DamlValue`.
480    #[test]
481    fn test_record_depth2_omitted_or_none() -> DamlJsonCodecResult<()> {
482        let grpc_value = daml_value!({foo: {?!}});
483        let expected = json!({});
484        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
485        assert_eq!(actual, expected);
486        Ok(())
487    }
488
489    /// `Depth2 with foo: Some None : data Depth2 = Depth2 with foo: Optional (Optional Int64)` -> `{ foo: [] }`
490    #[test]
491    fn test_record_depth2_some_none() -> DamlJsonCodecResult<()> {
492        let grpc_value = daml_value!({foo: {?={?!}}});
493        let expected = json!({ "foo": [] });
494        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
495        assert_eq!(actual, expected);
496        Ok(())
497    }
498
499    /// `Depth2 { foo: Some (Some 42) } : Depth2` -> `{ foo: [42] }`
500    #[test]
501    fn test_record_depth2_some_some() -> DamlJsonCodecResult<()> {
502        let grpc_value = daml_value!({foo: {?={?=42}}});
503        let expected = json!({ "foo": [42] });
504        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
505        assert_eq!(actual, expected);
506        Ok(())
507    }
508
509    #[test]
510    fn test_list_empty() -> DamlJsonCodecResult<()> {
511        let grpc_value = daml_value!([]);
512        let expected = json!([]);
513        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
514        assert_eq!(actual, expected);
515        Ok(())
516    }
517
518    #[test]
519    fn test_list_bool() -> DamlJsonCodecResult<()> {
520        let grpc_value = daml_value!([true, true, false, false]);
521        let expected = json!([true, true, false, false]);
522        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
523        assert_eq!(actual, expected);
524        Ok(())
525    }
526
527    #[test]
528    fn test_list_text() -> DamlJsonCodecResult<()> {
529        let grpc_value = daml_value!(["a", "b", "c"]);
530        let expected = json!(["a", "b", "c"]);
531        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
532        assert_eq!(actual, expected);
533        Ok(())
534    }
535
536    #[test]
537    fn test_list_opt_text() -> DamlJsonCodecResult<()> {
538        let grpc_value = daml_value!([{?="a"}, {?!}, {?="c"}]);
539        let expected = json!(["a", null, "c"]);
540        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
541        assert_eq!(actual, expected);
542        Ok(())
543    }
544
545    #[test]
546    fn test_list_record() -> DamlJsonCodecResult<()> {
547        let grpc_value = daml_value!([{
548            landlord: "Alice"::p,
549            tenant: "Bob"::p,
550            terms: "test terms"
551        },
552        {
553            landlord: "John"::p,
554            tenant: "Paul"::p,
555            terms: "more test terms"
556        }]);
557        let expected = json!([{
558            "landlord": "Alice",
559            "tenant": "Bob",
560            "terms": "test terms",
561        },
562        {
563            "landlord": "John",
564            "tenant": "Paul",
565            "terms": "more test terms",
566        }]);
567        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
568        assert_eq!(actual, expected);
569        Ok(())
570    }
571
572    #[test]
573    fn test_textmap_empty() -> DamlJsonCodecResult<()> {
574        let grpc_value = DamlValue::Map(vec![].into_iter().collect());
575        let expected = json!({});
576        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
577        assert_eq!(actual, expected);
578        Ok(())
579    }
580
581    #[test]
582    fn test_textmap_int() -> DamlJsonCodecResult<()> {
583        let grpc_value = DamlValue::Map(
584            vec![("foo".to_owned(), daml_value![42]), ("bar".to_owned(), daml_value![43])].into_iter().collect(),
585        );
586        let expected = json!({"foo": 42, "bar": 43});
587        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
588        assert_eq!(actual, expected);
589        Ok(())
590    }
591
592    #[test]
593    fn test_textmap_list_int() -> DamlJsonCodecResult<()> {
594        let grpc_value = DamlValue::Map(DamlTextMap::from(hashmap! {
595            "foo".to_owned() => daml_value![[1, 2, 3]],
596            "bar".to_owned() => daml_value![[4, 5, 6]]
597        }));
598        let expected = json!({"foo": [1, 2, 3], "bar": [4, 5, 6]});
599        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
600        assert_eq!(actual, expected);
601        Ok(())
602    }
603
604    #[test]
605    fn test_textmap_record() -> DamlJsonCodecResult<()> {
606        let grpc_value = DamlValue::Map(DamlTextMap::from(hashmap! {
607            "first".to_owned() => daml_value!({landlord: "Alice"::p, tenant: "Bob"::p, terms: "test terms"}),
608            "last".to_owned() => daml_value!({landlord: "John"::p, tenant: "Paul"::p, terms: "more test terms"})
609        }));
610        let expected = json!({
611        "first": {
612            "landlord": "Alice",
613            "tenant": "Bob",
614            "terms": "test terms",
615        },
616        "last": {
617            "landlord": "John",
618            "tenant": "Paul",
619            "terms": "more test terms",
620        }});
621        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
622        assert_eq!(actual, expected);
623        Ok(())
624    }
625
626    #[test]
627    fn test_genmap_empty() -> DamlJsonCodecResult<()> {
628        let grpc_value = DamlValue::GenMap(vec![].into_iter().collect());
629        let expected = json!([]);
630        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
631        assert_eq!(actual, expected);
632        Ok(())
633    }
634
635    #[test]
636    fn test_genmap_string_to_int() -> DamlJsonCodecResult<()> {
637        let grpc_value = DamlValue::GenMap(
638            vec![(daml_value!["foo"], daml_value![42]), (daml_value!["bar"], daml_value![43])].into_iter().collect(),
639        );
640        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
641        let key_foo_value = find_genmap_value(&actual, &json!["foo"])?;
642        let key_bar_value = find_genmap_value(&actual, &json!["bar"])?;
643        assert_eq!(key_foo_value, &json![42]);
644        assert_eq!(key_bar_value, &json![43]);
645        Ok(())
646    }
647
648    #[test]
649    fn test_genmap_int_to_string() -> DamlJsonCodecResult<()> {
650        let grpc_value = DamlValue::GenMap(
651            vec![(daml_value![42], daml_value!["foo"]), (daml_value![43], daml_value!["bar"])].into_iter().collect(),
652        );
653        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
654        let key_42_value = find_genmap_value(&actual, &json![42])?;
655        let key_43_value = find_genmap_value(&actual, &json![43])?;
656        assert_eq!(key_42_value, &json!["foo"]);
657        assert_eq!(key_43_value, &json!["bar"]);
658        Ok(())
659    }
660
661    #[test]
662    fn test_genmap_person_to_string() -> DamlJsonCodecResult<()> {
663        let grpc_value = DamlValue::GenMap(
664            vec![
665                (daml_value![{name: "John", age: 29}], daml_value!["foo"]),
666                (daml_value![{name: "Alice", age: 22}], daml_value!["bar"]),
667            ]
668            .into_iter()
669            .collect(),
670        );
671        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
672        let key_john_value = find_genmap_value(&actual, &json![{"name": "John", "age": 29}])?;
673        let key_alice_value = find_genmap_value(&actual, &json![{"name": "Alice", "age": 22}])?;
674        assert_eq!(key_john_value, &json!["foo"]);
675        assert_eq!(key_alice_value, &json!["bar"]);
676        Ok(())
677    }
678
679    #[test]
680    fn test_variant_bar() -> DamlJsonCodecResult<()> {
681        let grpc_value = daml_value![{=>Bar 42}];
682        let expected = json!({"tag": "Bar", "value": 42});
683        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
684        assert_eq!(actual, expected);
685        Ok(())
686    }
687
688    #[test]
689    fn test_variant_baz() -> DamlJsonCodecResult<()> {
690        let grpc_value = daml_value![{=>Baz}];
691        let expected = json!({"tag": "Baz", "value": {}});
692        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
693        assert_eq!(actual, expected);
694        Ok(())
695    }
696
697    #[test]
698    fn test_variant_quuz_none() -> DamlJsonCodecResult<()> {
699        let grpc_value = daml_value![{=>Quux {?!}}];
700        let expected = json!({"tag": "Quux", "value": null});
701        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
702        assert_eq!(actual, expected);
703        Ok(())
704    }
705
706    #[test]
707    fn test_variant_quuz_some() -> DamlJsonCodecResult<()> {
708        let grpc_value = daml_value![{=>Quux {?=42}}];
709        let expected = json!({"tag": "Quux", "value": 42});
710        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
711        assert_eq!(actual, expected);
712        Ok(())
713    }
714
715    #[test]
716    fn test_enum_enabled() -> DamlJsonCodecResult<()> {
717        let grpc_value = DamlValue::Enum(DamlEnum::new("Enabled", None));
718        let expected = json!("Enabled");
719        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
720        assert_eq!(actual, expected);
721        Ok(())
722    }
723
724    #[test]
725    fn test_enum_disabled() -> DamlJsonCodecResult<()> {
726        let grpc_value = DamlValue::Enum(DamlEnum::new("Disabled", None));
727        let expected = json!("Disabled");
728        let actual = JsonValueEncoder::default().encode_value(&grpc_value)?;
729        assert_eq!(actual, expected);
730        Ok(())
731    }
732
733    fn find_genmap_value<'a>(genmap: &'a Value, key: &Value) -> DamlJsonCodecResult<&'a Value> {
734        Ok(genmap
735            .try_array()?
736            .iter()
737            .find_map(|item| (item.try_array().ok()?.first()? == key).then(|| item))
738            .req()?
739            .try_array()?
740            .last()
741            .req()?)
742    }
743}