How do I test output of serde_json::to_string_pretty

I have a method that returns serde_json::to_string_pretty(). I cannot change the return.

I did make changes to the method so I need to write some unit tests against it. I cannot seem to figure out how to format my expected json.

Here's my test

fn test_encode_attributes_success() {
    let expected = json!({
      "address1": {
        "encoded": "63690509275174663089934667471948380740244018358024875547775652380902762701972",
        "raw": "101 Tela Lane"
      "zip": {
        "encoded": "87121",
        "raw": "87121"
      "city": {
        "encoded": "101327353979588246869873249766058188995681113722618593621043638294296500696424",
        "raw": "SLC"

    static TEST_CREDENTIAL_DATA: &str =
    r#"{"address2":["101 Wilson Lane"],

    let expected_json = serde_json::to_string_pretty(&expected).unwrap();
    let results_json = encode_attributes(TEST_CREDENTIAL_DATA).unwrap();
    assert_eq!(expected_json, results_json, "encode_attributes failed to return expected results");

and the output looks like this (hint: the order of the elements on the right (results_json) is different every time I run the test)

thread 'issuer_credential::tests::test_encode_attributes_success' panicked at 'assertion failed: `(left == right)`
  left: `"{\n  \"address1\": {\n    \"encoded\": \"63690509275174663089934667471948380740244018358024875547775652380902762701972\",\n    \"raw\": \"101 Tela Lane\"\n  },\n  \"city\": {\n    \"encoded\": \"101327353979588246869873249766058188995681113722618593621043638294296500696424\",\n    \"raw\": \"SLC\"\n  },\n  \"zip\": {\n    \"encoded\": \"87121\",\n    \"raw\": \"87121\"\n  }\n}"`,
 right: `"{\n  \"zip\": {\n    \"encoded\": \"87121\",\n    \"raw\": \"87121\"\n  },\n  \"city\": {\n    \"encoded\": \"101327353979588246869873249766058188995681113722618593621043638294296500696424\",\n    \"raw\": \"SLC\"\n  },\n  \"address2\": {\n    \"encoded\": \"68086943237164982734333428280784300550565381723532936263016368251445461241953\",\n    \"raw\": \"101 Wilson Lane\"\n  }\n}"`: encode_attributes failed to return expected results', src/


It seems serde has a feature flag (you can enable those in Cargo.toml) that allows to preserve the order of the input. See the release notes: Release v0.7.2 · serde-rs/json · GitHub

I ended up testing it differently. I take the result of encode_attributes and convert to a serde Value object, which lets me parse individual objects and get their properties.


let results_json = encode_attributes(TEST_CREDENTIAL_DATA).unwrap();

let results : Value = serde_json::from_str(&results_json).unwrap();
let address2 : &Value = &results["address2"];

assert_eq!("68086943237164982734333428280784300550565381723532936263016368251445461241953", address2["encoded"]);
assert_eq!("101 Wilson Lane", address2["raw"]);