...

Source file src/github.com/exponent-io/jsonpath/pathaction_test.go

Documentation: github.com/exponent-io/jsonpath

     1  package jsonpath
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestPathActionSingleMatch(t *testing.T) {
    14  
    15  	j := []byte(`
    16  	{
    17  		"foo": 1,
    18  		"bar": 2,
    19  		"test": "Hello, world!",
    20  		"baz": 123.1,
    21  		"array": [
    22  			{"foo": 1},
    23  			{"bar": 2},
    24  			{"baz": 3}
    25  		],
    26  		"subobj": {
    27  			"foo": 1,
    28  			"subarray": [1,2,3],
    29  			"subsubobj": {
    30  				"bar": 2,
    31  				"baz": 3,
    32  				"array": ["hello", "world"]
    33  			}
    34  		},
    35  		"bool": true
    36  	}`)
    37  
    38  	decodeCount := 0
    39  	decode := func(d *Decoder) interface{} {
    40  		decodeCount++
    41  		var v interface{}
    42  		err := d.Decode(&v)
    43  		assert.NoError(t, err)
    44  		return v
    45  	}
    46  
    47  	dc := NewDecoder(bytes.NewBuffer(j))
    48  	actions := &PathActions{}
    49  
    50  	actions.Add(func(d *Decoder) error {
    51  		assert.Equal(t, float64(2), decode(d))
    52  		return nil
    53  	}, "array", 1, "bar")
    54  
    55  	actions.Add(func(d *Decoder) error {
    56  		assert.Equal(t, "Hello, world!", decode(d))
    57  		return nil
    58  	}, "test")
    59  
    60  	actions.Add(func(d *Decoder) error {
    61  		assert.Equal(t, []interface{}{float64(1), float64(2), float64(3)}, decode(d))
    62  		return nil
    63  	}, "subobj", "subarray")
    64  
    65  	actions.Add(func(d *Decoder) error {
    66  		assert.Equal(t, float64(1), decode(d))
    67  		return nil
    68  	}, "foo")
    69  
    70  	actions.Add(func(d *Decoder) error {
    71  		assert.Equal(t, float64(2), decode(d))
    72  		return nil
    73  	}, "bar")
    74  
    75  	dc.Scan(actions)
    76  
    77  	assert.Equal(t, 5, decodeCount)
    78  }
    79  
    80  func TestPathActionAnyIndex(t *testing.T) {
    81  
    82  	j := []byte(`
    83  	{
    84  		"foo": 1,
    85  		"bar": 2,
    86  		"test": "Hello, world!",
    87  		"baz": 123.1,
    88  		"array": [
    89  			{"num": 1},
    90  			{"num": 2},
    91  			{"num": 3}
    92  		],
    93  		"subobj": {
    94  			"foo": 1,
    95  			"subarray": [1,2,3],
    96  			"subsubobj": {
    97  				"bar": 2,
    98  				"baz": 3,
    99  				"array": ["hello", "world"]
   100  			}
   101  		},
   102  		"bool": true
   103  	}`)
   104  
   105  	dc := NewDecoder(bytes.NewBuffer(j))
   106  	actions := &PathActions{}
   107  
   108  	numbers := []int{}
   109  	actions.Add(func(d *Decoder) (err error) {
   110  		var v int
   111  		err = d.Decode(&v)
   112  		require.NoError(t, err)
   113  		numbers = append(numbers, v)
   114  		return
   115  	}, "array", AnyIndex, "num")
   116  
   117  	numbers2 := []int{}
   118  	actions.Add(func(d *Decoder) (err error) {
   119  		var v int
   120  		err = d.Decode(&v)
   121  		require.NoError(t, err)
   122  		numbers2 = append(numbers2, v)
   123  		return
   124  	}, "subobj", "subarray", AnyIndex)
   125  
   126  	strings := []string{}
   127  	actions.Add(func(d *Decoder) (err error) {
   128  		var v string
   129  		err = d.Decode(&v)
   130  		require.NoError(t, err)
   131  		strings = append(strings, v)
   132  		return
   133  	}, "subobj", "subsubobj", "array", AnyIndex)
   134  
   135  	dc.Scan(actions)
   136  
   137  	assert.Equal(t, []int{1, 2, 3}, numbers)
   138  	assert.Equal(t, []int{1, 2, 3}, numbers2)
   139  	assert.Equal(t, []string{"hello", "world"}, strings)
   140  }
   141  
   142  func TestPathActionJsonStream(t *testing.T) {
   143  
   144  	j := []byte(`
   145  	{
   146      "make": "Porsche",
   147  		"model": "356 Coupé",
   148      "years": { "from": 1948, "to": 1965}
   149    }
   150    {
   151      "years": { "from": 1964, "to": 1969},
   152      "make": "Ford",
   153      "model": "GT40"
   154    }
   155    {
   156      "make": "Ferrari",
   157      "model": "308 GTB",
   158      "years": { "to": 1985, "from": 1975}
   159    }
   160    `)
   161  
   162  	dc := NewDecoder(bytes.NewBuffer(j))
   163  
   164  	var from, to []int
   165  	actions := &PathActions{}
   166  	actions.Add(func(d *Decoder) (err error) {
   167  		var v int
   168  		err = d.Decode(&v)
   169  		require.NoError(t, err)
   170  		from = append(from, v)
   171  		return
   172  	}, "years", "from")
   173  	actions.Add(func(d *Decoder) (err error) {
   174  		var v int
   175  		err = d.Decode(&v)
   176  		require.NoError(t, err)
   177  		to = append(to, v)
   178  		return
   179  	}, "years", "to")
   180  
   181  	var err error
   182  	var ok = true
   183  	for ok && err == nil {
   184  		ok, err = dc.Scan(actions)
   185  		if err != io.EOF {
   186  			require.NoError(t, err)
   187  		}
   188  	}
   189  
   190  	assert.Equal(t, []int{1948, 1964, 1975}, from)
   191  	assert.Equal(t, []int{1965, 1969, 1985}, to)
   192  }
   193  
   194  func TestPathActionJsonSubObjects(t *testing.T) {
   195  
   196  	j := []byte(`
   197      {
   198        "set": "cars",
   199      	"data": [
   200          {
   201            "make": "Porsche",
   202        		"model": "356 Coupé",
   203            "years": { "from": 1948, "to": 1965}
   204          },
   205          {
   206            "years": { "from": 1964, "to": 1969},
   207            "make": "Ford",
   208            "model": "GT40"
   209          },
   210          {
   211            "make": "Ferrari",
   212            "model": "308 GTB",
   213            "years": { "to": 1985, "from": 1975}
   214          }
   215        ],
   216        "more": true
   217      }
   218    `)
   219  
   220  	dc := NewDecoder(bytes.NewBuffer(j))
   221  
   222  	var from, to []int
   223  	actions := &PathActions{}
   224  	actions.Add(func(d *Decoder) (err error) {
   225  		var v int
   226  		err = d.Decode(&v)
   227  		require.NoError(t, err)
   228  		from = append(from, v)
   229  		return
   230  	}, "data", AnyIndex, "years", "from")
   231  	actions.Add(func(d *Decoder) (err error) {
   232  		var v int
   233  		err = d.Decode(&v)
   234  		require.NoError(t, err)
   235  		to = append(to, v)
   236  		return
   237  	}, "data", AnyIndex, "years", "to")
   238  
   239  	var err error
   240  	var ok = true
   241  	for ok && err == nil {
   242  		_, err = dc.Scan(actions)
   243  		if err != io.EOF {
   244  			require.NoError(t, err)
   245  		}
   246  	}
   247  
   248  	assert.Equal(t, []int{1948, 1964, 1975}, from)
   249  	assert.Equal(t, []int{1965, 1969, 1985}, to)
   250  }
   251  
   252  func TestPathActionSeekThenScan(t *testing.T) {
   253  
   254  	j := []byte(`
   255      {
   256        "set": "cars",
   257      	"data": [
   258          {
   259            "make": "Porsche",
   260        		"model": "356 Coupé",
   261            "years": { "from": 1948, "to": 1965}
   262          },
   263          {
   264            "years": { "from": 1964, "to": 1969},
   265            "make": "Ford",
   266            "model": "GT40"
   267          },
   268          {
   269            "make": "Ferrari",
   270            "model": "308 GTB",
   271            "years": { "to": 1985, "from": 1975}
   272          }
   273        ],
   274        "more": true
   275      }
   276    `)
   277  
   278  	dc := NewDecoder(bytes.NewBuffer(j))
   279  	ok, err := dc.SeekTo("data", 0)
   280  	require.NoError(t, err)
   281  	require.True(t, ok)
   282  
   283  	var from, to int
   284  	actions := &PathActions{}
   285  	actions.Add(func(d *Decoder) (err error) {
   286  		err = d.Decode(&from)
   287  		require.NoError(t, err)
   288  		return
   289  	}, "years", "from")
   290  	actions.Add(func(d *Decoder) (err error) {
   291  		err = d.Decode(&to)
   292  		require.NoError(t, err)
   293  		return
   294  	}, "years", "to")
   295  
   296  	outs := []string{}
   297  	for ok && err == nil {
   298  		ok, err = dc.Scan(actions)
   299  		if err != io.EOF {
   300  			require.NoError(t, err)
   301  		}
   302  		if err == nil || err == io.EOF {
   303  			outs = append(outs, fmt.Sprintf("%v-%v", from, to))
   304  		}
   305  	}
   306  
   307  	assert.Equal(t, []string{"1948-1965", "1964-1969", "1975-1985"}, outs)
   308  }
   309  
   310  func TestPathActionSeekOffsetThenScan(t *testing.T) {
   311  
   312  	j := []byte(`
   313      {
   314        "set": "cars",
   315      	"data": [
   316          {
   317            "make": "Porsche",
   318        		"model": "356 Coupé",
   319            "years": { "from": 1948, "to": 1965}
   320          },
   321          {
   322            "years": { "from": 1964, "to": 1969},
   323            "make": "Ford",
   324            "model": "GT40"
   325          },
   326          {
   327            "make": "Ferrari",
   328            "model": "308 GTB",
   329            "years": { "to": 1985, "from": 1975}
   330          }
   331        ],
   332        "more": true
   333      }
   334    `)
   335  
   336  	dc := NewDecoder(bytes.NewBuffer(j))
   337  	ok, err := dc.SeekTo("data", 1)
   338  	require.NoError(t, err)
   339  	require.True(t, ok)
   340  
   341  	var from, to int
   342  	actions := &PathActions{}
   343  	actions.Add(func(d *Decoder) (err error) {
   344  		err = d.Decode(&from)
   345  		require.NoError(t, err)
   346  		return
   347  	}, "years", "from")
   348  	actions.Add(func(d *Decoder) (err error) {
   349  		err = d.Decode(&to)
   350  		require.NoError(t, err)
   351  		return
   352  	}, "years", "to")
   353  
   354  	outs := []string{}
   355  	for ok && err == nil {
   356  		ok, err = dc.Scan(actions)
   357  		if err != io.EOF {
   358  			require.NoError(t, err)
   359  		}
   360  		if err == nil || err == io.EOF {
   361  			outs = append(outs, fmt.Sprintf("%v-%v", from, to))
   362  		}
   363  	}
   364  
   365  	assert.Equal(t, []string{"1964-1969", "1975-1985"}, outs)
   366  }
   367  
   368  func TestPathActionSeekThenScanThenScan(t *testing.T) {
   369  
   370  	j := []byte(`
   371      {
   372        "set": "cars",
   373      	"data": [
   374          {
   375            "make": "Porsche",
   376        		"model": "356 Coupé",
   377            "years": { "from": 1948, "to": 1965}
   378          },
   379          {
   380            "years": { "from": 1964, "to": 1969},
   381            "make": "Ford",
   382            "model": "GT40"
   383          }
   384        ],
   385        "more": [
   386          {
   387            "make": "Ferrari",
   388            "model": "308 GTB",
   389            "years": { "to": 1985, "from": 1975}
   390          }
   391        ]
   392      }
   393    `)
   394  
   395  	dc := NewDecoder(bytes.NewBuffer(j))
   396  	ok, err := dc.SeekTo("data", 0)
   397  	require.NoError(t, err)
   398  	require.True(t, ok)
   399  
   400  	var from, to int
   401  	actions := &PathActions{}
   402  	actions.Add(func(d *Decoder) (err error) {
   403  		err = d.Decode(&from)
   404  		require.NoError(t, err)
   405  		return
   406  	}, "years", "from")
   407  	actions.Add(func(d *Decoder) (err error) {
   408  		err = d.Decode(&to)
   409  		require.NoError(t, err)
   410  		return
   411  	}, "years", "to")
   412  
   413  	outs := []string{}
   414  	for ok && err == nil {
   415  		ok, err = dc.Scan(actions)
   416  		if err != io.EOF {
   417  			require.NoError(t, err)
   418  		}
   419  		if err == nil || err == io.EOF {
   420  			outs = append(outs, fmt.Sprintf("%v-%v", from, to))
   421  		}
   422  	}
   423  
   424  	assert.Equal(t, []string{"1948-1965", "1964-1969"}, outs)
   425  
   426  	ok, err = dc.SeekTo("more", 0)
   427  	require.NoError(t, err)
   428  	require.True(t, ok)
   429  	outs = []string{}
   430  	for ok && err == nil {
   431  		ok, err = dc.Scan(actions)
   432  		if err != io.EOF {
   433  			require.NoError(t, err)
   434  		}
   435  		if err == nil || err == io.EOF {
   436  			outs = append(outs, fmt.Sprintf("%v-%v", from, to))
   437  		}
   438  	}
   439  
   440  	assert.Equal(t, []string{"1975-1985"}, outs)
   441  }
   442  
   443  func TestPathActionSeekThenScanHetero(t *testing.T) {
   444  
   445  	j := []byte(`
   446      {
   447        "set": "cars",
   448      	"data": [
   449          {
   450            "make": "Porsche",
   451        		"model": "356 Coupé",
   452            "years": { "from": 1948, "to": 1965}
   453          },
   454          ["other","random","stuff"],
   455          {
   456            "years": { "from": 1964, "to": 1969},
   457            "make": "Ford",
   458            "model": "GT40"
   459          },
   460          {},
   461          "str",
   462          {
   463            "make": "Ferrari",
   464            "model": "308 GTB",
   465            "years": { "to": 1985, "from": 1975}
   466          }
   467        ],
   468        "more": true
   469      }
   470    `)
   471  
   472  	dc := NewDecoder(bytes.NewBuffer(j))
   473  	ok, err := dc.SeekTo("data", 0)
   474  	require.NoError(t, err)
   475  	require.True(t, ok)
   476  
   477  	var from, to int
   478  	actions := &PathActions{}
   479  	actions.Add(func(d *Decoder) (err error) {
   480  		err = d.Decode(&from)
   481  		require.NoError(t, err)
   482  		return
   483  	}, "years", "from")
   484  	actions.Add(func(d *Decoder) (err error) {
   485  		err = d.Decode(&to)
   486  		require.NoError(t, err)
   487  		return
   488  	}, "years", "to")
   489  
   490  	outs := []string{}
   491  	for ok && err == nil {
   492  		ok, err = dc.Scan(actions)
   493  		if err != io.EOF {
   494  			require.NoError(t, err)
   495  		}
   496  		if (err == nil || err == io.EOF) && (from != 0 && to != 0) {
   497  			outs = append(outs, fmt.Sprintf("%v-%v", from, to))
   498  			from, to = 0, 0
   499  		}
   500  	}
   501  
   502  	assert.Equal(t, []string{"1948-1965", "1964-1969", "1975-1985"}, outs)
   503  }
   504  
   505  func TestPathActionNested(t *testing.T) {
   506  
   507  	j := []byte(`
   508      {
   509        "set": "cars",
   510      	"data": [
   511          {
   512            "make": "Porsche",
   513        		"model": "356 Coupé",
   514            "years": { "from": 1948, "to": 1965}
   515          },
   516          {
   517            "years": { "from": 1964, "to": 1969},
   518            "make": "Ford",
   519            "model": "GT40"
   520          },
   521          {
   522            "make": "Ferrari",
   523            "model": "308 GTB",
   524            "years": { "to": 1985, "from": 1975}
   525          }
   526        ],
   527        "more": true
   528      }
   529    `)
   530  
   531  	var from, to int
   532  	caractions := &PathActions{}
   533  	caractions.Add(func(d *Decoder) (err error) {
   534  		err = d.Decode(&from)
   535  		require.NoError(t, err)
   536  		return
   537  	}, "years", "from")
   538  	caractions.Add(func(d *Decoder) (err error) {
   539  		err = d.Decode(&to)
   540  		require.NoError(t, err)
   541  		return
   542  	}, "years", "to")
   543  
   544  	outs := []string{}
   545  
   546  	actions := &PathActions{}
   547  	actions.Add(func(d *Decoder) error {
   548  
   549  		_, err := d.Scan(caractions)
   550  		if err != nil {
   551  			return err
   552  		}
   553  		outs = append(outs, fmt.Sprintf("%v-%v", from, to))
   554  		return nil
   555  
   556  	}, "data", AnyIndex)
   557  
   558  	ok, err := NewDecoder(bytes.NewBuffer(j)).Scan(actions)
   559  	assert.NoError(t, err)
   560  	assert.False(t, ok)
   561  
   562  	assert.Equal(t, []string{"1948-1965", "1964-1969", "1975-1985"}, outs)
   563  }
   564  

View as plain text