apioo / typeschema

TypeSchema is a JSON format to describe data models in a language neutral format
https://typeschema.org/
MIT License
142 stars 3 forks source link

Protobuf serialization doesn't have stable numbers #20

Open tvh opened 2 days ago

tvh commented 2 days ago

When serializing to protobuf, the binary protocol is not generated in a migration-safe manner. Say I do the following specs:

V1: typeschema:

{
  "definitions": {
    "Student": {
      "type": "struct",
      "properties": {
        "firstName": {
          "type": "string"
        },
        "age": {
          "type": "integer"
        }
      }
    }
  },
  "root": "Student"
}

protobuf:

message Student {
    optional string firstName = 1 [json_name="firstName"];
    optional int64 age = 2 [json_name="age"];
}

V2 typeschema:

{
  "definitions": {
    "Student": {
      "type": "struct",
      "properties": {
        "firstName": {
          "type": "string"
        },
        "lastName": {
          "type": "string"
        },
        "age": {
          "type": "integer"
        }
      }
    }
  },
  "root": "Student"
}

protobuf:

message Student {
    optional string firstName = 1 [json_name="firstName"];
    optional string lastName = 2 [json_name="lastName"];
    optional int64 age = 3 [json_name="age"];
}

Now the age field change it's name and type, breaking the binary protocol.

chriskapp commented 2 days ago

Hi @tvh thanks for the feedback, I am not sure whether we can solve this at our generator since the generator only has information about the current specification, it does not know, whether there is a previous version where the age property was placed at a different position. The only solution which I could image would be to build the integer based on the property name, through this the number would be stable and only changes if you also change the property name, maybe this would be better?

tvh commented 2 days ago

I think the only correct solution would be to add the tag to the typeschema model.

Deriving the number from the field name may work for most objects but will sometimes create conflicts. You only have ~500k numbers to choose from (see https://protobuf.dev/programming-guides/proto2/#assigning). That means collisions are relatively unlikely but far from impossible.