OpenAPITools / OpenAPITools/openapi-generator

[REQ] [go] wish to optionally strict json.Unmarshall in decode()

Open
#11,832 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Enhancement: Feature
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

[go] wish to optionally strict json.Unmarshall in decode()

currently when generating go code json.Unmarshall is used to map json objects into go structures.
however by default json.Unmarshall does not throw an error when a json key has no matching go strcture to map on.
As stated on

json#Unmarshal:

 By default, object keys which don't have a corresponding struct field are ignored (see Decoder.DisallowUnknownFields for an alternative).

example generated code for decode (6.0.0-SNAPSHOT):

func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) {
	if len(b) == 0 {
		return nil
	}
	if s, ok := v.(*string); ok {
		*s = string(b)
		return nil
	}
	if f, ok := v.(**os.File); ok {
		*f, err = ioutil.TempFile("", "HttpClientFile")
		if err != nil {
			return
		}
		_, err = (*f).Write(b)
		if err != nil {
			return
		}
		_, err = (*f).Seek(0, io.SeekStart)
		return
	}
	if xmlCheck.MatchString(contentType) {
		if err = xml.Unmarshal(b, v); err != nil {
			return err
		}
		return nil
	}
	if jsonCheck.MatchString(contentType) {
		if actualObj, ok := v.(interface{ GetActualInstance() interface{} }); ok { // oneOf, anyOf schemas
			if unmarshalObj, ok := actualObj.(interface{ UnmarshalJSON([]byte) error }); ok { // make sure it has UnmarshalJSON defined
				if err = unmarshalObj.UnmarshalJSON(b); err != nil {
					return err
				}
			} else {
				return errors.New("Unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined")
			}
		} else if err = json.Unmarshal(b, v); err != nil { // simple model
			return err
		}
		return nil
	}
	return errors.New("undefined response type")
}

In case of //simple model, reading(decoding) json structures might ignore
objects/keys are not decoded (in case of schema mismatch)

Wish to optionally generate (json) decoder with strict schema checking

I would prefer to have an early warning option to catch the case of schema/data mismatch when
reading/decoding json data, to make sure we are aware (with error)
objects/keys are going to be lost.

Currently i notice a "newstrictDecoder()" in client.go but it looks like
not be-ing used for this purpose.

I was expecting(hoping) the option "--strict-spec true" would trigger a feature
also to check the actual data to match on schema but it is "only" checking the specfile, not actual data
as it seems.
--strict-spec Feature described in #1086

Current "shortcut"

Currently put in as a hack client.go:decode to perform such check:

func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) {
        if len(b) == 0 {
                return nil
        }
        if s, ok := v.(*string); ok {
                *s = string(b)
                return nil
        }
        if f, ok := v.(**os.File); ok {
                *f, err = ioutil.TempFile("", "HttpClientFile")
                if err != nil {
                        return
                }
                _, err = (*f).Write(b)
                if err != nil {
                        return
                }
                _, err = (*f).Seek(0, io.SeekStart)
                return
        }
        if xmlCheck.MatchString(contentType) {
                if err = xml.Unmarshal(b, v); err != nil {
                        return err
                }
                return nil
        }
        if jsonCheck.MatchString(contentType) {
                if actualObj, ok := v.(interface{ GetActualInstance() interface{} }); ok { // oneOf, anyOf schemas
                        if unmarshalObj, ok := actualObj.(interface{ UnmarshalJSON([]byte) error }); ok { // make sure it has UnmarshalJSON defined
                                if err = unmarshalObj.UnmarshalJSON(b); err != nil {
                                        return err
                                }
                        } else {
                                return errors.New("Unknown type with GetActualInstance but no unmarshalObj.UnmarshalJSON defined")
                        }
                } else if err = safeJSONUnmarshalbyte(b, v); err != nil { // Hack ArFi to implement strict json map checks
                        // err = json.Unmarshal(b, v); err != nil { // simple model
                        return err
                }
                return nil
        }
        return errors.New("undefined response type")
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the generated Go client.go and its decode() path, including the existing newstrictDecoder() and the --strict-spec handling linked to #1086. Trace how simple JSON models and oneOf/anyOf schemas are decoded. Done means an optional strict mode reports unknown JSON keys while preserving the current default behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.