...

Source file src/github.com/aws/smithy-go/encoding/json/decoder_util.go

Documentation: github.com/aws/smithy-go/encoding/json

     1  package json
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  )
     9  
    10  // DiscardUnknownField discards unknown fields from a decoder body.
    11  // This function is useful while deserializing a JSON body with additional
    12  // unknown information that should be discarded.
    13  func DiscardUnknownField(decoder *json.Decoder) error {
    14  	// This deliberately does not share logic with CollectUnknownField, even
    15  	// though it could, because if we were to delegate to that then we'd incur
    16  	// extra allocations and general memory usage.
    17  	v, err := decoder.Token()
    18  	if err == io.EOF {
    19  		return nil
    20  	}
    21  	if err != nil {
    22  		return err
    23  	}
    24  
    25  	if _, ok := v.(json.Delim); ok {
    26  		for decoder.More() {
    27  			err = DiscardUnknownField(decoder)
    28  		}
    29  		endToken, err := decoder.Token()
    30  		if err != nil {
    31  			return err
    32  		}
    33  		if _, ok := endToken.(json.Delim); !ok {
    34  			return fmt.Errorf("invalid JSON : expected json delimiter, found %T %v",
    35  				endToken, endToken)
    36  		}
    37  	}
    38  
    39  	return nil
    40  }
    41  
    42  // CollectUnknownField grabs the contents of unknown fields from the decoder body
    43  // and returns them as a byte slice. This is useful for skipping unknown fields without
    44  // completely discarding them.
    45  func CollectUnknownField(decoder *json.Decoder) ([]byte, error) {
    46  	result, err := collectUnknownField(decoder)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	buff := bytes.NewBuffer(nil)
    52  	encoder := json.NewEncoder(buff)
    53  
    54  	if err := encoder.Encode(result); err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	return buff.Bytes(), nil
    59  }
    60  
    61  func collectUnknownField(decoder *json.Decoder) (interface{}, error) {
    62  	// Grab the initial value. This could either be a concrete value like a string or a a
    63  	// delimiter.
    64  	token, err := decoder.Token()
    65  	if err == io.EOF {
    66  		return nil, nil
    67  	}
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	// If it's an array or object, we'll need to recurse.
    73  	delim, ok := token.(json.Delim)
    74  	if ok {
    75  		var result interface{}
    76  		if delim == '{' {
    77  			result, err = collectUnknownObject(decoder)
    78  			if err != nil {
    79  				return nil, err
    80  			}
    81  		} else {
    82  			result, err = collectUnknownArray(decoder)
    83  			if err != nil {
    84  				return nil, err
    85  			}
    86  		}
    87  
    88  		// Discard the closing token. decoder.Token handles checking for matching delimiters
    89  		if _, err := decoder.Token(); err != nil {
    90  			return nil, err
    91  		}
    92  		return result, nil
    93  	}
    94  
    95  	return token, nil
    96  }
    97  
    98  func collectUnknownArray(decoder *json.Decoder) ([]interface{}, error) {
    99  	// We need to create an empty array here instead of a nil array, since by getting
   100  	// into this function at all we necessarily have seen a non-nil list.
   101  	array := []interface{}{}
   102  
   103  	for decoder.More() {
   104  		value, err := collectUnknownField(decoder)
   105  		if err != nil {
   106  			return nil, err
   107  		}
   108  		array = append(array, value)
   109  	}
   110  
   111  	return array, nil
   112  }
   113  
   114  func collectUnknownObject(decoder *json.Decoder) (map[string]interface{}, error) {
   115  	object := make(map[string]interface{})
   116  
   117  	for decoder.More() {
   118  		key, err := collectUnknownField(decoder)
   119  		if err != nil {
   120  			return nil, err
   121  		}
   122  
   123  		// Keys have to be strings, which is particularly important as the encoder
   124  		// won't except a map with interface{} keys
   125  		stringKey, ok := key.(string)
   126  		if !ok {
   127  			return nil, fmt.Errorf("expected string key, found %T", key)
   128  		}
   129  
   130  		value, err := collectUnknownField(decoder)
   131  		if err != nil {
   132  			return nil, err
   133  		}
   134  
   135  		object[stringKey] = value
   136  	}
   137  
   138  	return object, nil
   139  }
   140  

View as plain text