简体   繁体   中英

Resolving "$ref" in serde_json/serde_yaml

What is the best way to recursively resolve all JSON $ref in JSON documents?

A direct approach is to create a Deserialize implementation that accepts either a {"$ref"} object or a desired value, say an enum like this:

enum JRef<T> {
    Value(T),
    Ref(URI),
}

impl<'de, T> Deserialize<'de> for JRef<T> { ... }

But this would require me to wrap all my types in JRef<T> , so my derive(Deserialize) schema struct is filled with the boilerplate:

#[derive(Deserialize)]
struct Foo {
    a: JRef<Bar>,
    b: JRef<(JRef<Qux>, JRef<Corge>)>,
    ...
}

In addition, the resolution of the reference is also boilerplate.

I understand that the direct deserialization of a type should not depend on some external state, so it makes sense to first deserialize into a JRef and then resolve them later. But to prevent writing boilerplate code, the resolution performed later could be performed using a custom proc-macro that derives a JRef-free-type of the original type, which implement a trait that accepts a foreign function and resolves URIs using the foreign function.

So far, I have dug deep into the dependency ecosystem in order to just resolve a single $ref . Do I really need to do all these, or is there a simpler solution I have missed?

I think: It depends. What is the further purpose of your code?

  • Do you just need deserialization for code generation?
  • Are you modifying the JSON and serialize it again?

For the first case, there is a good example: schemafy A) In schemafy_lib/src/schema.rs the schema to be serialized can be found. It contains a $ref, of type Option. B) Further, schemafy_lib/src/lib.rs contains an Expander, transforming the $ref into Rust source code. (At least that is my understanding.)

I have to deal with the latter case - serializing as well as deserializing. From the first example a take A and skip B. I plan to put my Schema into an object, hiding the $ref while clients may deals with JSON objects transparently.

Comments are welcome.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM