Blame vendor/github.com/getkin/kin-openapi/jsoninfo/unmarshal.go

Packit Service 3a6627
package jsoninfo
Packit Service 3a6627
Packit Service 3a6627
import (
Packit Service 3a6627
	"encoding/json"
Packit Service 3a6627
	"fmt"
Packit Service 3a6627
	"reflect"
Packit Service 3a6627
)
Packit Service 3a6627
Packit Service 3a6627
// UnmarshalStrictStruct function:
Packit Service 3a6627
//   * Unmarshals struct fields, ignoring UnmarshalJSON(...) and fields without 'json' tag.
Packit Service 3a6627
//   * Correctly handles StrictStruct
Packit Service 3a6627
func UnmarshalStrictStruct(data []byte, value StrictStruct) error {
Packit Service 3a6627
	decoder, err := NewObjectDecoder(data)
Packit Service 3a6627
	if err != nil {
Packit Service 3a6627
		return err
Packit Service 3a6627
	}
Packit Service 3a6627
	return value.DecodeWith(decoder, value)
Packit Service 3a6627
}
Packit Service 3a6627
Packit Service 3a6627
type ObjectDecoder struct {
Packit Service 3a6627
	Data            []byte
Packit Service 3a6627
	remainingFields map[string]json.RawMessage
Packit Service 3a6627
}
Packit Service 3a6627
Packit Service 3a6627
func NewObjectDecoder(data []byte) (*ObjectDecoder, error) {
Packit Service 3a6627
	var remainingFields map[string]json.RawMessage
Packit Service 3a6627
	if err := json.Unmarshal(data, &remainingFields); err != nil {
Packit Service 3a6627
		return nil, fmt.Errorf("Failed to unmarshal extension properties: %v\nInput: %s", err, data)
Packit Service 3a6627
	}
Packit Service 3a6627
	return &ObjectDecoder{
Packit Service 3a6627
		Data:            data,
Packit Service 3a6627
		remainingFields: remainingFields,
Packit Service 3a6627
	}, nil
Packit Service 3a6627
}
Packit Service 3a6627
Packit Service 3a6627
// DecodeExtensionMap returns all properties that were not decoded previously.
Packit Service 3a6627
func (decoder *ObjectDecoder) DecodeExtensionMap() map[string]json.RawMessage {
Packit Service 3a6627
	return decoder.remainingFields
Packit Service 3a6627
}
Packit Service 3a6627
Packit Service 3a6627
func (decoder *ObjectDecoder) DecodeStructFieldsAndExtensions(value interface{}) error {
Packit Service 3a6627
	reflection := reflect.ValueOf(value)
Packit Service 3a6627
	if reflection.Kind() != reflect.Ptr {
Packit Service 3a6627
		panic(fmt.Errorf("Value %T is not a pointer", value))
Packit Service 3a6627
	}
Packit Service 3a6627
	if reflection.IsNil() {
Packit Service 3a6627
		panic(fmt.Errorf("Value %T is nil", value))
Packit Service 3a6627
	}
Packit Service 3a6627
	reflection = reflection.Elem()
Packit Service 3a6627
	for (reflection.Kind() == reflect.Interface || reflection.Kind() == reflect.Ptr) && !reflection.IsNil() {
Packit Service 3a6627
		reflection = reflection.Elem()
Packit Service 3a6627
	}
Packit Service 3a6627
	reflectionType := reflection.Type()
Packit Service 3a6627
	if reflectionType.Kind() != reflect.Struct {
Packit Service 3a6627
		panic(fmt.Errorf("Value %T is not a struct", value))
Packit Service 3a6627
	}
Packit Service 3a6627
	typeInfo := GetTypeInfo(reflectionType)
Packit Service 3a6627
Packit Service 3a6627
	// Supported fields
Packit Service 3a6627
	fields := typeInfo.Fields
Packit Service 3a6627
	remainingFields := decoder.remainingFields
Packit Service 3a6627
	for fieldIndex, field := range fields {
Packit Service 3a6627
		// Fields without JSON tag are ignored
Packit Service 3a6627
		if !field.HasJSONTag {
Packit Service 3a6627
			continue
Packit Service 3a6627
		}
Packit Service 3a6627
Packit Service 3a6627
		// Get data
Packit Service 3a6627
		fieldData, exists := remainingFields[field.JSONName]
Packit Service 3a6627
		if !exists {
Packit Service 3a6627
			continue
Packit Service 3a6627
		}
Packit Service 3a6627
Packit Service 3a6627
		// Unmarshal
Packit Service 3a6627
		if field.TypeIsUnmarshaller {
Packit Service 3a6627
			fieldType := field.Type
Packit Service 3a6627
			isPtr := false
Packit Service 3a6627
			if fieldType.Kind() == reflect.Ptr {
Packit Service 3a6627
				fieldType = fieldType.Elem()
Packit Service 3a6627
				isPtr = true
Packit Service 3a6627
			}
Packit Service 3a6627
			fieldValue := reflect.New(fieldType)
Packit Service 3a6627
			if err := fieldValue.Interface().(json.Unmarshaler).UnmarshalJSON(fieldData); err != nil {
Packit Service 3a6627
				if field.MultipleFields {
Packit Service 3a6627
					i := fieldIndex + 1
Packit Service 3a6627
					if i < len(fields) && fields[i].JSONName == field.JSONName {
Packit Service 3a6627
						continue
Packit Service 3a6627
					}
Packit Service 3a6627
				}
Packit Service 3a6627
				return fmt.Errorf("Error while unmarshalling property '%s' (%s): %v",
Packit Service 3a6627
					field.JSONName, fieldValue.Type().String(), err)
Packit Service 3a6627
			}
Packit Service 3a6627
			if !isPtr {
Packit Service 3a6627
				fieldValue = fieldValue.Elem()
Packit Service 3a6627
			}
Packit Service 3a6627
			reflection.FieldByIndex(field.Index).Set(fieldValue)
Packit Service 3a6627
Packit Service 3a6627
			// Remove the field from remaining fields
Packit Service 3a6627
			delete(remainingFields, field.JSONName)
Packit Service 3a6627
		} else {
Packit Service 3a6627
			fieldPtr := reflection.FieldByIndex(field.Index)
Packit Service 3a6627
			if fieldPtr.Kind() != reflect.Ptr || fieldPtr.IsNil() {
Packit Service 3a6627
				fieldPtr = fieldPtr.Addr()
Packit Service 3a6627
			}
Packit Service 3a6627
			if err := json.Unmarshal(fieldData, fieldPtr.Interface()); err != nil {
Packit Service 3a6627
				if field.MultipleFields {
Packit Service 3a6627
					i := fieldIndex + 1
Packit Service 3a6627
					if i < len(fields) && fields[i].JSONName == field.JSONName {
Packit Service 3a6627
						continue
Packit Service 3a6627
					}
Packit Service 3a6627
				}
Packit Service 3a6627
				return fmt.Errorf("Error while unmarshalling property '%s' (%s): %v",
Packit Service 3a6627
					field.JSONName, fieldPtr.Type().String(), err)
Packit Service 3a6627
			}
Packit Service 3a6627
Packit Service 3a6627
			// Remove the field from remaining fields
Packit Service 3a6627
			delete(remainingFields, field.JSONName)
Packit Service 3a6627
		}
Packit Service 3a6627
	}
Packit Service 3a6627
	return nil
Packit Service 3a6627
}