Enum jomini::json::DuplicateKeyMode

source ·
pub enum DuplicateKeyMode {
    Group,
    Preserve,
    KeyValuePairs,
}
Expand description

Controls JSON structure when duplicate keys are encountered

It’s debatable whether duplicate keys is valid JSON, so this allows one to customize output depending how flexible a downstream client is at handling JSON.

The options are either:

  • Group values into an array under a single field
  • Preserve the duplicate keys
  • Rewrite objects as an array of key value pairs

Variants§

§

Group

Group values into an array under a single field

use jomini::{TextTape, json::{JsonOptions, DuplicateKeyMode}};

let tape = TextTape::from_slice(b"a={b=1} c={b=1 b=2}")?;
let reader = tape.windows1252_reader();

let options = JsonOptions::new()
    .with_duplicate_keys(DuplicateKeyMode::Group);

let actual = reader.json()
    .with_options(options)
    .to_string();
assert_eq!(actual, r#"{"a":{"b":1},"c":{"b":[1,2]}}"#);

As shown above, downstream clients will need to be flexible enough to handle grouped and ungrouped keys, and may prove cumbersome or challenging to leverage automatic deserialization logic. Python or Javascript clients may like this output due to their more dynamic typing nature.

Grouping keys together will have a small but measurable impact on performance

§

Preserve

Preserve the duplicate keys (the default behavior)

use jomini::{TextTape, json::{JsonOptions, DuplicateKeyMode}};

let tape = TextTape::from_slice(b"a={b=1} c={b=1 b=2}")?;
let reader = tape.windows1252_reader();

let actual = reader.json()
    .with_options(JsonOptions::new())
    .to_string();
assert_eq!(actual, r#"{"a":{"b":1},"c":{"b":1,"b":2}}"#);

Preserving duplicate keys is the default mode as it represents the most concise output and most closely matches the input.

Insertion order of an object’s keys are maintained.

Python and Javascript clients may not like this output as their builtin JSON modules don’t handle duplicate keys well. However, lower level JSON parsers like simd-json tend to handle duplicate keys just fine.

§

KeyValuePairs

Rewrite objects as an array of 2 element arrays (the key and the value).

use jomini::{TextTape, json::{JsonOptions, DuplicateKeyMode}};

let tape = TextTape::from_slice(b"c=0 b={1 2}")?;
let reader = tape.windows1252_reader();

let options = JsonOptions::new()
    .with_duplicate_keys(DuplicateKeyMode::KeyValuePairs);

let actual = reader.json()
    .with_options(options)
    .to_string();
assert_eq!(actual, r#"{"type":"obj","val":[["c",0],["b",{"type":"array","val":[1,2]}]]}"#);

Objects and arrays are now transformed into adjacently tagged objects (to borrow a term from serde). Objects have a type of obj and arrays have a type of array. This adjacently tagged object is needed to disambiguate between objects and arrays if both are going to be represented with JSON arrays.

This output has the largest departure from the input and is the most verbose, but it allows one to use inflexible DOM parsers like those seen in Python and Javascript and still maintain the positioning of duplicate keys. Preserving positioning is important when interpretting an object is dependant on the order of the keys and duplicate keys may affect subsequent fields.

Trait Implementations§

source§

impl Clone for DuplicateKeyMode

source§

fn clone(&self) -> DuplicateKeyMode

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for DuplicateKeyMode

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for DuplicateKeyMode

source§

fn eq(&self, other: &DuplicateKeyMode) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Copy for DuplicateKeyMode

source§

impl Eq for DuplicateKeyMode

source§

impl StructuralPartialEq for DuplicateKeyMode

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.