#deserialize-json #json #duplicate #serde #multiple #overlapping

macro serde-deserialize-duplicates

A rust crate with helper macros providing an alternate implementation of serde's Deserialize for cases when duplicate values exist in the source data

3 releases

0.1.2 Jul 8, 2024
0.1.1 Jul 4, 2024
0.1.0 Jul 3, 2024

#1746 in Encoding

MIT/Apache

17KB
228 lines

Serde Duplicate Deserialization Helper Crate

Description

A rust crate with helper macros providing an alternate implementation of serde's Deserialize for cases when duplicate values exist in the source data.


lib.rs:

Serde Deserialize Duplicates Macros

This crate provides utilities for a very specific purpose: deserializing data with serde with frequent duplicate keys. It provides two helper macros - [DeserializeFirstDuplicate] and [DeserializeLastDuplicate] to allow a selection of order for this end.

Using this crate

Matching Duplicate Names

Take, for example, the following JSON:

{
    "myNumber": 34,
    "myNumber": 67
}

According to the JSON spec, it is perfectly valid JSON data.

Sometimes we interface with APIs out of our control which can return data like this, and we simply do not care which value we take, only that we have a value and we do not have a runtime panic.

For the following struct, a runtime panic would occur in case the data above was deserialized, due to the duplicate keys.

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct MyStruct {
   #[serde(rename = "myNumber")]
    my_number: i32
}

Thus, this crate provides alternatives to Deserialize, used as follows:

use serde::Serialize;
use serde_deserialize_duplicates::DeserializeFirstDuplicate;

#[derive(Serialize, DeserializeFirstDuplicate)]
struct MyStruct {
   #[serde(rename = "myNumber")]
    my_number: i32
}

Now, by replacing Deserialize with this crate's [DeserializeFirstDuplicate], we can simply use the first instance of "my_number" we encounter and ignore the rest. If you are looking for the last value, see [DeserializeLastDuplicate].

Aliased Duplicate Names

This crate also supports deserializing in the case where there is overlapping interpretations of an aliased value.

For example, take this JSON:

{
    "breed": "Labarador",
    "type": "Labarador"
}

Sometimes we have two fields which exist in JSON that provide identical information and we only want to deserialize one of them in the case we get one.

This can be achieved as follows:

use serde::Serialize;
use serde_deserialize_duplicates::DeserializeLastDuplicate;

#[derive(Serialize, DeserializeLastDuplicate)]
struct Dog {
   #[serde(alias = "type")]
    breed: String
}

Default fallback values

Occasionally, we may want to load some data which can or cannot exist, and may or may not be a duplicate at the same time.

Serde's default attribute is supported for this purpose, either deserializing successfully or using a fallback default value.

use serde::Serialize;
use serde_deserialize_duplicates::DeserializeLastDuplicate;

#[derive(Serialize, DeserializeLastDuplicate)]
struct Dog {
   #[serde(default)]
    occurs_more_than_once: Option<String>
}

Dependencies

~0.3–1MB
~21K SLoC