0

I'm trying to construct a JSON in rust using serde using structs.

{
  "parent": { "database_id": "123" },
  "properties": {
      "title": {
        "title": [
          {
            "text": {
              "content": "Yurts in Big Sur, 123"
            }
          }
        ]
      }
    }
}

There's a lot of nested structures. Should I create a struct for each nest? In the case of the two "title" properties. How do I handle that?

I tried to create a struct for each nest.

Here's how it looks like

#[derive(Serialize)]
struct DBRow {
    parent: Parent,
    properties: Properties,
}

#[derive(Serialize)]
struct Parent {
    database_id: String
}

#[derive(Serialize)]
struct Properties {
    title: PropTitle
}

#[derive(Serialize)]
struct PropTitle {
    title: Vec<Text>
}

#[derive(Serialize)]
struct Text {
    content: String
}

#[derive(Deserialize)]
struct CreateUser {
    username: String,
}
Xin Li
  • 1
  • 3

2 Answers2

0

You are missing the dezeralization for the text field

"text": {
    "content": "Yurts in Big Sur, 123"
}

Instead of having a Vec<Text> in PropTitle, you need another struct in between that has the text field.

#[derive(Deserialize, Serialize)]
struct PropTitle {
    title: Vec<TextEntry>,
}

#[derive(Deserialize, Serialize)]
struct TextEntry {
    text: Text,
}

#[derive(Deserialize, Serialize)]
struct Text {
    content: String,
}
pigeonhands
  • 3,066
  • 15
  • 26
0

In general, yes if you want to stick with using derive, you have little choice besides defining a rust struct for each level and "type" of structure in your JSON. I only have a few mitigating points:

  • You could abbreviate the title thing a bit by having a #[derive(Serialize)] struct Titled<T> { title: T } and then using it as struct DBRow { properties: Titled<Titled<Vec<Text>>>, … }. Playground. But I doubt it's of much use because:
  • You probably have more than one property, so I suspect you'll end up with something like struct DBRow { properties: HashMap<String, Property>, … } and #[derive(Serialize)] #[serde(rename_all = "snake_case"))] enum Property { Title (Vec<Text>) } anyway.
  • If you don't like working with the deeply nested set of structs in your rust code, you can make serde automatically convert structs after de-/serialization with from and into.
  • I made a crate to make this kind of definition easier to read, structstruck, but it still requires defining a lot of structs

You can of course define custom serializers, but that will likely end up being more work than defining the rust structs.

Caesar
  • 6,733
  • 4
  • 38
  • 44