Processing data with serde

I have a large struct GameObject that contains script objects, I want to read the struct through serde.json like this

struct GameObject{
    ...
    script: String,
    scripts: Vec<String>,
    ...
}

compile the scripts to some AST, and serialize/deserialize via bincode

struct GameObject{
    ...
    script: AST,
    scripts: Vec<AST>,
    ...
}

Is there a good way to do this without writing two separate structs? I want to avoid code repetition on a large struct.

I don't understand what you mean. If you want to serialize/deserialize your own data types, you can just derive the pertinent traits on them. No duplication of code or type declarations is needed.

I want to read the scripts as strings via json and write them as ASTs in binary format.

In this case, you are probably looking for serde_transcode.

Sorry if I'm not communicating clearly. I want to implement two separate methods of serialization/deserialization on the same object.

Thanks for the mention of transcode. It's probably gonna help my project but not what I'm looking for right now.

Then you'll need to use two separate serialization format libraries. Serde in itself is generic and doesn't perform any serialization. It merely maps your data structure to a tree of primitives and general collections. Turning that into an intelligible serialized representation is the job of serialization formats.

1 Like

One option is to make your GameObject struct parametric, like this:

struct GameObject<T> {
    ...
    script: T,
    scripts: Vec<T>,
    ...
}

This way you can implement generically the part of your logic which is common for String and AST representations, while the conversion between them would look something like

impl From<GameObject<String>> for GameObject<Ast> { ... }

At worst, if your logic turns out to bee non-generic, you can implement functions for GameObject<String> and GameObject<Ast> separately. Note that you can't have functions with the same name on those types.

2 Likes

If I understand you, I believe you want something like:

#[derive(...)]
struct Ast(...);
#[derive(...)]
struct Foo<T> {
   script: T,
   scripts: Vec<T>,
}
type AstFoo = Foo<Ast>;
type StringFoo = Foo<String>;

Yes, that's the suggestion. Whether it's reasonable for your particular use case I can't say without knowing more. The core question is how much of your logic is really generic, and how complex would be the required trait bounds.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.