github.com/RevenueMonster/sqlike@v1.0.6/jsonb/object.go (about)

     1  package jsonb
     2  
     3  import (
     4  	"strings"
     5  )
     6  
     7  // ReadObject :
     8  func (r *Reader) ReadObject(cb func(*Reader, string) error) error {
     9  	c := r.nextToken()
    10  	if c != '{' {
    11  		return ErrInvalidJSON{
    12  			callback: "ReadObject",
    13  			message:  "expect start with { for object",
    14  		}
    15  	}
    16  
    17  	var (
    18  		k   string
    19  		err error
    20  	)
    21  
    22  	for {
    23  		c = r.nextToken()
    24  		if c == '}' {
    25  			break
    26  		}
    27  
    28  		if c != '"' {
    29  			return ErrInvalidJSON{
    30  				callback: "ReadObject",
    31  				message:  "expect \" for object key",
    32  			}
    33  		}
    34  
    35  		k, err = r.unreadByte().ReadString()
    36  		if err != nil {
    37  			return err
    38  		}
    39  
    40  		c = r.nextToken()
    41  		if c != ':' {
    42  			return ErrInvalidJSON{
    43  				callback: "ReadObject",
    44  				message:  "expect : after object key",
    45  			}
    46  		}
    47  
    48  		v, err := r.ReadBytes()
    49  		if err != nil {
    50  			return err
    51  		}
    52  
    53  		it := NewReader(v)
    54  		if err := cb(it, k); err != nil {
    55  			return err
    56  		}
    57  
    58  		c = r.nextToken()
    59  		if c != ',' {
    60  			break
    61  		}
    62  	}
    63  
    64  	if c != '}' {
    65  		return ErrInvalidJSON{
    66  			callback: "ReadObject",
    67  			message:  "expect end with } for object",
    68  		}
    69  	}
    70  	return nil
    71  }
    72  
    73  // ReadFlattenObject :
    74  func (r *Reader) ReadFlattenObject(cb func(*Reader, string) error) error {
    75  	level := 1
    76  	c := r.nextToken()
    77  	if c != '{' {
    78  		return ErrInvalidJSON{
    79  			callback: "ReadFlattenObject",
    80  			message:  "expect start with { for object",
    81  		}
    82  	}
    83  
    84  	var (
    85  		paths []string
    86  		key   string
    87  		err   error
    88  	)
    89  
    90  keyLoop:
    91  	for {
    92  		c = r.nextToken()
    93  		if c == '}' {
    94  			r.unreadByte()
    95  			goto valueLoop
    96  		}
    97  
    98  		if c != '"' {
    99  			return ErrInvalidJSON{
   100  				callback: "ReadObject",
   101  				message:  "expect \" for object key",
   102  			}
   103  		}
   104  
   105  		key, err = r.unreadByte().ReadString()
   106  		if err != nil {
   107  			return err
   108  		}
   109  
   110  		paths = append(paths, key)
   111  
   112  		c = r.nextToken()
   113  		if c != ':' {
   114  			return ErrInvalidJSON{
   115  				callback: "ReadObject",
   116  				message:  "expect : after object key",
   117  			}
   118  		}
   119  
   120  		c = r.nextToken()
   121  		switch c {
   122  		case '{':
   123  			level++
   124  			goto keyLoop
   125  
   126  		default:
   127  			v, err := r.unreadByte().ReadBytes()
   128  			if err != nil {
   129  				return err
   130  			}
   131  
   132  			k := strings.Join(paths, ".")
   133  			it := NewReader(v)
   134  			if err := cb(it, k); err != nil {
   135  				return err
   136  			}
   137  		}
   138  
   139  	valueLoop:
   140  		c = r.nextToken()
   141  		switch c {
   142  		case '}':
   143  			level--
   144  			if level < 1 {
   145  				break keyLoop
   146  			}
   147  			paths = paths[:level-1]
   148  			c = r.nextToken()
   149  			if c != ',' {
   150  				r.unreadByte()
   151  			}
   152  
   153  		case ',':
   154  			paths = append([]string{}, paths[:len(paths)-1]...)
   155  
   156  		default:
   157  			break
   158  
   159  		}
   160  	}
   161  
   162  	if c != '}' {
   163  		return ErrInvalidJSON{
   164  			callback: "ReadFlattenObject",
   165  			message:  "expect end with } for object",
   166  		}
   167  	}
   168  	return nil
   169  }