...

Source file src/github.com/launchdarkly/go-jsonstream/v3/jreader/reader.go

Documentation: github.com/launchdarkly/go-jsonstream/v3/jreader

     1  package jreader
     2  
     3  // Reader is a high-level API for reading JSON data sequentially.
     4  //
     5  // It is designed to make writing custom unmarshallers for application types as convenient as
     6  // possible. The general usage pattern is as follows:
     7  //
     8  // - Values are parsed in the order that they appear.
     9  //
    10  // - In general, the caller should know what data type is expected. Since it is common for
    11  // properties to be nullable, the methods for reading scalar types have variants for allowing
    12  // a null instead of the specified type. If the type is completely unknown, use Any.
    13  //
    14  // - For reading array or object structures, the Array and Object methods return a struct that
    15  // keeps track of additional reader state while that structure is being parsed.
    16  //
    17  // - If any method encounters an error (due to either malformed JSON, or well-formed JSON that
    18  // did not match the caller's data type expectations), the Reader permanently enters a failed
    19  // state and remembers that error; all subsequent method calls will return the same error and no
    20  // more parsing will happen. This means that the caller does not necessarily have to check the
    21  // error return value of any individual method, although it can.
    22  type Reader struct {
    23  	tr                tokenReader
    24  	awaitingReadValue bool // used by ArrayState & ObjectState
    25  	err               error
    26  }
    27  
    28  // Error returns the first error that the Reader encountered, if the Reader is in a failed state,
    29  // or nil if it is still in a good state.
    30  func (r *Reader) Error() error {
    31  	return r.err
    32  }
    33  
    34  // RequireEOF returns nil if all of the input has been consumed (not counting whitespace), or an
    35  // error if not.
    36  func (r *Reader) RequireEOF() error {
    37  	if !r.tr.EOF() {
    38  		return SyntaxError{Message: errMsgDataAfterEnd, Offset: r.tr.LastPos()}
    39  	}
    40  	return nil
    41  }
    42  
    43  // AddError sets the Reader's error value and puts it into a failed state. If the parameter is nil
    44  // or the Reader was already in a failed state, it does nothing.
    45  func (r *Reader) AddError(err error) {
    46  	if r.err == nil {
    47  		r.err = err
    48  	}
    49  }
    50  
    51  // ReplaceError sets the Reader's error value and puts it into a failed state, replacing any
    52  // previously reported error. If the parameter is nil, it does nothing (a failed state cannot be
    53  // changed to a non-failed state).
    54  func (r *Reader) ReplaceError(err error) {
    55  	if err != nil {
    56  		r.err = err
    57  	}
    58  }
    59  
    60  // Null attempts to read a null value, returning an error if the next token is not a null.
    61  func (r *Reader) Null() error {
    62  	r.awaitingReadValue = false
    63  	if r.err != nil {
    64  		return r.err
    65  	}
    66  	isNull, err := r.tr.Null()
    67  	if isNull || err != nil {
    68  		return err
    69  	}
    70  	return r.typeErrorForCurrentToken(NullValue, false)
    71  }
    72  
    73  // Bool attempts to read a boolean value.
    74  //
    75  // If there is a parsing error, or the next value is not a boolean, the return value is false
    76  // and the Reader enters a failed state, which you can detect with Error().
    77  func (r *Reader) Bool() bool {
    78  	r.awaitingReadValue = false
    79  	if r.err != nil {
    80  		return false
    81  	}
    82  	val, err := r.tr.Bool()
    83  	if err != nil {
    84  		r.err = err
    85  		return false
    86  	}
    87  	return val
    88  }
    89  
    90  // BoolOrNull attempts to read either a boolean value or a null. In the case of a boolean, the return
    91  // values are (value, true); for a null, they are (false, false).
    92  //
    93  // If there is a parsing error, or the next value is neither a boolean nor a null, the return values
    94  // are (false, false) and the Reader enters a failed state, which you can detect with Error().
    95  func (r *Reader) BoolOrNull() (value bool, nonNull bool) {
    96  	r.awaitingReadValue = false
    97  	if r.err != nil {
    98  		return false, false
    99  	}
   100  	isNull, err := r.tr.Null()
   101  	if isNull || err != nil {
   102  		r.err = err
   103  		return false, false
   104  	}
   105  	val, err := r.tr.Bool()
   106  	if err != nil {
   107  		r.err = typeErrorForNullableValue(err)
   108  		return false, false
   109  	}
   110  	return val, true
   111  }
   112  
   113  // Int attempts to read a numeric value and returns it as an int.
   114  //
   115  // If there is a parsing error, or the next value is not a number, the return value is zero and
   116  // the Reader enters a failed state, which you can detect with Error(). Non-numeric types are never
   117  // converted to numbers.
   118  func (r *Reader) Int() int {
   119  	return int(r.Float64())
   120  }
   121  
   122  // IntOrNull attempts to read either an integer numeric value or a null. In the case of a number, the
   123  // return values are (value, true); for a null, they are (0, false).
   124  //
   125  // If there is a parsing error, or the next value is neither a number nor a null, the return values
   126  // are (0, false) and the Reader enters a failed state, which you can detect with Error().
   127  func (r *Reader) IntOrNull() (int, bool) {
   128  	val, nonNull := r.Float64OrNull()
   129  	return int(val), nonNull
   130  }
   131  
   132  // Float64 attempts to read a numeric value and returns it as a float64.
   133  //
   134  // If there is a parsing error, or the next value is not a number, the return value is zero and
   135  // the Reader enters a failed state, which you can detect with Error(). Non-numeric types are never
   136  // converted to numbers.
   137  func (r *Reader) Float64() float64 {
   138  	r.awaitingReadValue = false
   139  	if r.err != nil {
   140  		return 0
   141  	}
   142  	val, err := r.tr.Number()
   143  	if err != nil {
   144  		r.err = err
   145  		return 0
   146  	}
   147  	return val
   148  }
   149  
   150  // Float64OrNull attempts to read either a numeric value or a null. In the case of a number, the
   151  // return values are (value, true); for a null, they are (0, false).
   152  //
   153  // If there is a parsing error, or the next value is neither a number nor a null, the return values
   154  // are (0, false) and the Reader enters a failed state, which you can detect with Error().
   155  func (r *Reader) Float64OrNull() (float64, bool) {
   156  	r.awaitingReadValue = false
   157  	if r.err != nil {
   158  		return 0, false
   159  	}
   160  	isNull, err := r.tr.Null()
   161  	if isNull || err != nil {
   162  		r.err = err
   163  		return 0, false
   164  	}
   165  	val, err := r.tr.Number()
   166  	if err != nil {
   167  		r.err = typeErrorForNullableValue(err)
   168  		return 0, false
   169  	}
   170  	return val, true
   171  }
   172  
   173  // String attempts to read a string value.
   174  //
   175  // If there is a parsing error, or the next value is not a string, the return value is "" and
   176  // the Reader enters a failed state, which you can detect with Error(). Types other than string
   177  // are never converted to strings.
   178  func (r *Reader) String() string {
   179  	r.awaitingReadValue = false
   180  	if r.err != nil {
   181  		return ""
   182  	}
   183  	val, err := r.tr.String()
   184  	if err != nil {
   185  		r.err = err
   186  		return ""
   187  	}
   188  	return val
   189  }
   190  
   191  // StringOrNull attempts to read either a string value or a null. In the case of a string, the
   192  // return values are (value, true); for a null, they are ("", false).
   193  //
   194  // If there is a parsing error, or the next value is neither a string nor a null, the return values
   195  // are ("", false) and the Reader enters a failed state, which you can detect with Error().
   196  func (r *Reader) StringOrNull() (string, bool) {
   197  	r.awaitingReadValue = false
   198  	if r.err != nil {
   199  		return "", false
   200  	}
   201  	isNull, err := r.tr.Null()
   202  	if isNull || err != nil {
   203  		r.err = err
   204  		return "", false
   205  	}
   206  	val, err := r.tr.String()
   207  	if err != nil {
   208  		r.err = typeErrorForNullableValue(err)
   209  		return "", false
   210  	}
   211  	return val, true
   212  }
   213  
   214  // Array attempts to begin reading a JSON array value. If successful, the return value will be an
   215  // ArrayState containing the necessary state for iterating through the array elements.
   216  //
   217  // The ArrayState is used only for the iteration state; to read the value of each array element, you
   218  // will still use the Reader's methods.
   219  //
   220  // If there is a parsing error, or the next value is not an array, the returned ArrayState is a stub
   221  // whose Next() method always returns false, and the Reader enters a failed state, which you can
   222  // detect with Error().
   223  //
   224  // See ArrayState for example code.
   225  func (r *Reader) Array() ArrayState {
   226  	return r.tryArray(false)
   227  }
   228  
   229  // ArrayOrNull attempts to either begin reading an JSON array value, or read a null. In the case of an
   230  // array, the return value will be an ArrayState containing the necessary state for iterating through
   231  // the array elements; the ArrayState's IsDefined() method will return true. In the case of a null, the
   232  // returned ArrayState will be a stub whose Next() and IsDefined() methods always returns false.
   233  //
   234  // The ArrayState is used only for the iteration state; to read the value of each array element, you
   235  // will still use the Reader's methods.
   236  //
   237  // If there is a parsing error, or the next value is neither an array nor a null, the return value is
   238  // the same as for a null but the Reader enters a failed state, which you can detect with Error().
   239  //
   240  // See ArrayState for example code.
   241  func (r *Reader) ArrayOrNull() ArrayState {
   242  	return r.tryArray(true)
   243  }
   244  
   245  func (r *Reader) tryArray(allowNull bool) ArrayState {
   246  	r.awaitingReadValue = false
   247  	if r.err != nil {
   248  		return ArrayState{}
   249  	}
   250  	if allowNull {
   251  		isNull, err := r.tr.Null()
   252  		if err != nil {
   253  			r.err = err
   254  			return ArrayState{}
   255  		}
   256  		if isNull {
   257  			return ArrayState{}
   258  		}
   259  	}
   260  	gotDelim, err := r.tr.Delimiter('[')
   261  	if err != nil {
   262  		r.err = err
   263  		return ArrayState{}
   264  	}
   265  	if gotDelim {
   266  		return ArrayState{r: r}
   267  	}
   268  	r.err = r.typeErrorForCurrentToken(ArrayValue, allowNull)
   269  	return ArrayState{}
   270  }
   271  
   272  // Object attempts to begin reading a JSON object value. If successful, the return value will be an
   273  // ObjectState containing the necessary state for iterating through the object properties.
   274  //
   275  // The ObjectState is used only for the iteration state; to read the value of each property, you
   276  // will still use the Reader's methods.
   277  //
   278  // If there is a parsing error, or the next value is not an object, the returned ObjectState is a stub
   279  // whose Next() method always returns false, and the Reader enters a failed state, which you can
   280  // detect with Error().
   281  //
   282  // See ObjectState for example code.
   283  func (r *Reader) Object() ObjectState {
   284  	return r.tryObject(false)
   285  }
   286  
   287  // ObjectOrNull attempts to either begin reading an JSON object value, or read a null. In the case of an
   288  // object, the return value will be an ObjectState containing the necessary state for iterating through
   289  // the object properties; the ObjectState's IsDefined() method will return true. In the case of a null,
   290  // the returned ObjectState will be a stub whose Next() and IsDefined() methods always returns false.
   291  //
   292  // The ObjectState is used only for the iteration state; to read the value of each property, you
   293  // will still use the Reader's methods.
   294  //
   295  // If there is a parsing error, or the next value is neither an object nor a null, the return value is
   296  // the same as for a null but the Reader enters a failed state, which you can detect with Error().
   297  //
   298  // See ObjectState for example code.
   299  func (r *Reader) ObjectOrNull() ObjectState {
   300  	return r.tryObject(true)
   301  }
   302  
   303  func (r *Reader) tryObject(allowNull bool) ObjectState {
   304  	r.awaitingReadValue = false
   305  	if r.err != nil {
   306  		return ObjectState{}
   307  	}
   308  	if allowNull {
   309  		isNull, err := r.tr.Null()
   310  		if err != nil || isNull {
   311  			r.err = err
   312  			return ObjectState{}
   313  		}
   314  	}
   315  	gotDelim, err := r.tr.Delimiter('{')
   316  	if err != nil {
   317  		r.err = err
   318  		return ObjectState{}
   319  	}
   320  	if gotDelim {
   321  		return ObjectState{r: r}
   322  	}
   323  	r.err = r.typeErrorForCurrentToken(ObjectValue, allowNull)
   324  	return ObjectState{}
   325  }
   326  
   327  // Any reads a single value of any type, if it is a scalar value or a null, or prepares to read
   328  // the value if it is an array or object.
   329  //
   330  // The returned AnyValue's Kind field indicates the value type. If it is BoolValue, NumberValue,
   331  // or StringValue, check the corresponding Bool, Number, or String property. If it is ArrayValue
   332  // or ObjectValue, the AnyValue's Array or Object field has been initialized with an ArrayState or
   333  // ObjectState just as if you had called the Reader's Array or Object method.
   334  //
   335  // If there is a parsing error, the return value is the same as for a null and the Reader enters
   336  // a failed state, which you can detect with Error().
   337  func (r *Reader) Any() AnyValue {
   338  	r.awaitingReadValue = false
   339  	if r.err != nil {
   340  		return AnyValue{}
   341  	}
   342  	v, err := r.tr.Any()
   343  	if err != nil {
   344  		r.err = err
   345  		return AnyValue{}
   346  	}
   347  	switch v.Kind {
   348  	case BoolValue:
   349  		return AnyValue{Kind: v.Kind, Bool: v.Bool}
   350  	case NumberValue:
   351  		return AnyValue{Kind: v.Kind, Number: v.Number}
   352  	case StringValue:
   353  		return AnyValue{Kind: v.Kind, String: v.String}
   354  	case ArrayValue:
   355  		return AnyValue{Kind: v.Kind, Array: ArrayState{r: r}}
   356  	case ObjectValue:
   357  		return AnyValue{Kind: v.Kind, Object: ObjectState{r: r}}
   358  	default:
   359  		return AnyValue{Kind: NullValue}
   360  	}
   361  }
   362  
   363  // SkipValue consumes and discards the next JSON value of any type. For an array or object value, it
   364  // recurses to also consume and discard all array elements or object properties.
   365  func (r *Reader) SkipValue() error {
   366  	r.awaitingReadValue = false
   367  	if r.err != nil {
   368  		return r.err
   369  	}
   370  	v := r.Any()
   371  	if v.Kind == ArrayValue {
   372  		for v.Array.Next() {
   373  		}
   374  	} else if v.Kind == ObjectValue {
   375  		for v.Object.Next() {
   376  		}
   377  	}
   378  	return r.err
   379  }
   380  
   381  func typeErrorForNullableValue(err error) error {
   382  	if err != nil {
   383  		switch e := err.(type) { //nolint:gocritic
   384  		case TypeError:
   385  			e.Nullable = true
   386  			return e
   387  		}
   388  	}
   389  	return err
   390  }
   391  
   392  func (r *Reader) typeErrorForCurrentToken(expected ValueKind, nullable bool) error {
   393  	v, err := r.tr.Any()
   394  	if err != nil {
   395  		return err
   396  	}
   397  	return TypeError{Expected: expected, Actual: v.Kind, Offset: r.tr.LastPos(), Nullable: nullable}
   398  }
   399  

View as plain text