referrerpolicy=no-referrer-when-downgrade

Macro frame_support::build_struct_json_patch

source ·
macro_rules! build_struct_json_patch {
    (
		$($struct_type:ident)::+ { $($body:tt)* }
	) => { ... };
    ($($struct_type:ident)::+, $all_keys:ident @ { $($body:tt)* }) => { ... };
    ($($struct_type:ident)::+, $all_keys:ident @ $key:ident:  $($type:ident)::+ { $($body:tt)* } ) => { ... };
    ($($struct_type:ident)::+, $all_keys:ident @ $key:ident:  $($type:ident)::+ { $($body:tt)* },  $($tail:tt)*) => { ... };
    ($($struct_type:ident)::+, $all_keys:ident @ $key:ident: $value:expr, $($tail:tt)* ) => { ... };
    ($($struct_type:ident)::+, $all_keys:ident @ $key:ident: $value:expr ) => { ... };
    ($($struct_type:ident)::+, $all_keys:ident @ $key:ident, $($tail:tt)* ) => { ... };
    ($($struct_type:ident)::+, $all_keys:ident @ $key:ident ) => { ... };
    ($($struct_type:ident)::+, $all_keys:ident @ ..$update:expr ) => { ... };
    ($($struct_type:ident)::+, $all_keys:ident  @ $(,)?) => { ... };
}
Expand description

Creates a JSON patch for given struct_type, supporting recursive field initialization.

This macro creates a default struct_type, initializing specified fields (which can be nested) with the provided values. Any fields not explicitly given are initialized with their default values. The macro then serializes the fully initialized structure into a JSON blob, retaining only the fields that were explicitly provided, either partially or fully initialized.

Using this macro prevents errors from manually creating JSON objects, such as typos or inconsistencies with the struct_type structure, by relying on the actual struct definition. This ensures the generated JSON is valid and reflects any future changes to the structure.

§Example

use frame_support::build_struct_json_patch;
#[derive(Default, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct RuntimeGenesisConfig {
    a_field: u32,
    b_field: B,
    c_field: u32,
}

#[derive(Default, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct B {
	i_field: u32,
	j_field: u32,
}
impl B {
	fn new() -> Self {
		Self { i_field: 0, j_field: 2 }
	}
}

assert_eq!(
	build_struct_json_patch! ( RuntimeGenesisConfig {
		a_field: 66,
	}),
	serde_json::json!({
			"aField": 66,
	})
);

assert_eq!(
	build_struct_json_patch! ( RuntimeGenesisConfig {
		//"partial" initialization of `b_field`
		b_field: B {
			i_field: 2,
		}
	}),
	serde_json::json!({
		"bField": {"iField": 2}
	})
);

assert_eq!(
	build_struct_json_patch! ( RuntimeGenesisConfig {
		a_field: 66,
		//"full" initialization of `b_field`
		b_field: B::new()
	}),
	serde_json::json!({
		"aField": 66,
		"bField": {"iField": 0, "jField": 2}
	})
);

In this example:

	build_struct_json_patch! ( RuntimeGenesisConfig {
		b_field: B {
			i_field: 2,
		}
	}),

b_field is partially initialized, it will be expanded to:

RuntimeGenesisConfig {
		b_field {
			i_field: 2,
			..Default::default()
		},
		..Default::default()
}

While all other fields are initialized with default values. The macro serializes this, retaining only the provided fields.