Skip to content

Commit

Permalink
Use json.RawMessage when polymorphic fields contain submessages (#88)
Browse files Browse the repository at this point in the history
* Use json.RawMessage when polymorphic fields contain submessages

So far, these fields were represented as `interface{}`, which means that
the JSON library parsed these fields. However, they contain opaque data,
which makes it very inconvenient to work with such a message. Now,
fields with a submessage are represented as json.RawMessage, so that
applications can re-parse these submessages into the correct structure
more easily.

If the list of types only contains fundamental types, we stick with
`interface{}`.

Signed-off-by: Cornelius Weig <22861411+corneliusweig@users.noreply.github.com>

* Address review comments

Signed-off-by: Cornelius Weig <22861411+corneliusweig@users.noreply.github.com>

---------

Signed-off-by: Cornelius Weig <22861411+corneliusweig@users.noreply.github.com>
  • Loading branch information
corneliusweig committed Feb 13, 2024
1 parent f1fa77f commit e7addf5
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 21 deletions.
18 changes: 15 additions & 3 deletions cmd/gentypes/gentypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ func parsePropertyType(propValue map[string]interface{}) string {
log.Fatal("property with no type or ref:", propValue)
}

switch propType.(type) {
switch typ := propType.(type) {
case string:
switch propType {
switch typ {
case "string":
return "string"
case "number":
Expand Down Expand Up @@ -124,10 +124,22 @@ func parsePropertyType(propValue map[string]interface{}) string {
}

case []interface{}:
// This field is polymorphic so it needs a generic type.
for _, el := range typ {
s, ok := el.(string)
if !ok {
log.Fatalf("property type contains a non-string of type %T: %#v", el, typ)
}
if s == "object" || s == "array" {
// It contains non-fundamental types, so treat it as opaque.
return "json.RawMessage"
}
}
// The possible types are all fundamental types, so we can use interface{}.
return "interface{}"

default:
log.Fatal("unknown property type", propType)
log.Fatalf("unknown property type %T (%#v)", typ, typ)
}

panic("unreachable")
Expand Down
2 changes: 1 addition & 1 deletion codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,7 @@ var exitedEventStruct = ExitedEvent{
var terminatedEventString = `{"seq":5,"type":"event","event":"terminated","body":{"restart":true}}`
var terminatedEventStruct = TerminatedEvent{
Event: *newEvent(5, "terminated"),
Body: TerminatedEventBody{Restart: true},
Body: TerminatedEventBody{Restart: json.RawMessage(`true`)},
}

var threadEventString = `{"seq":6,"type":"event","event":"thread","body":{"reason":"started","threadId":18}}`
Expand Down
34 changes: 17 additions & 17 deletions schematypes.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e7addf5

Please sign in to comment.