jsonschema: marshal to bools (#247)

Marshal the empty schema to true, and its negation to false.

This is technically a breaking behavior change, but a properly written
consumer of JSON Schema will not notice.

For #244.

Fixes #230.
This commit is contained in:
Jonathan Amsterdam 2025-08-06 11:41:02 -04:00 • committed by GitHub
commit c132621eb0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 18 additions and 7 deletions

View file

@ -204,6 +204,7 @@ func (s *Schema) MarshalJSON() ([]byte, error) {
if err := s.basicChecks(); err != nil {
return nil, err
}
// Marshal either Type or Types as "type".
var typ any
switch {
@ -219,7 +220,19 @@ func (s *Schema) MarshalJSON() ([]byte, error) {
Type: typ,
schemaWithoutMethods: (*schemaWithoutMethods)(s),
}
return marshalStructWithMap(&ms, "Extra")
bs, err := marshalStructWithMap(&ms, "Extra")
if err != nil {
return nil, err
}
// Marshal {} as true and {"not": {}} as false.
// It is wasteful to do this here instead of earlier, but much easier.
switch {
case bytes.Equal(bs, []byte(`{}`)):
bs = []byte("true")
case bytes.Equal(bs, []byte(`{"not":true}`)):
bs = []byte("false")
}
return bs, nil
}
func (s *Schema) UnmarshalJSON(data []byte) error {

View file

@ -54,9 +54,9 @@ func TestJSONRoundTrip(t *testing.T) {
for _, tt := range []struct {
in, want string
}{
{`true`, `{}`}, // boolean schemas become object schemas
{`false`, `{"not":{}}`},
{`{"type":"", "enum":null}`, `{}`}, // empty fields are omitted
{`true`, `true`},
{`false`, `false`},
{`{"type":"", "enum":null}`, `true`}, // empty fields are omitted
{`{"minimum":1}`, `{"minimum":1}`},
{`{"minimum":1.0}`, `{"minimum":1}`}, // floating-point integers lose their fractional part
{`{"minLength":1.0}`, `{"minLength":1}`}, // some floats are unmarshaled into ints, but you can't tell