risor-io / risor

Fast and flexible scripting for Go developers and DevOps.
https://risor.io
Apache License 2.0
576 stars 24 forks source link

Odd behaviour unmarshalling json string containing `items` object #247

Open voigt opened 1 week ago

voigt commented 1 week ago

Hey,

lately I noticed an inconsistent while unmarshalling a json struct:

What I did

issuesJson := `{
  "data": {
    "test": {
        "edges": [
        {"hello":"world"},
        {"hello":"world2"}
        ]
    },
    "items": {
        "edges": [
        {"hello":"world"},
        {"hello":"world2"}
        ]
    }
  }
}
`

issues := json.unmarshal(issuesJson)
print(issues.data.test)
print(issues.data.items)

Which produced following output

$ risor main.rsr
map[edges:[map[hello:world] map[hello:world2]]]
0x102bc6380

Expected output

$ risor main.rsr
map[edges:[map[hello:world] map[hello:world2]]]
map[edges:[map[hello:world] map[hello:world2]]]

risor version

$ risor version 
1.6.0

I think this is a very odd behaviour, and probably not intended, as it prevents me from accessing any items of data.items.

myzie commented 1 week ago

Hi @voigt I will look at this.

myzie commented 1 week ago

Ah, yeah this is a bit confusing for sure. What is happening is that items is a built-in function on maps in Risor, like the items built-in on Python dicts.

Built-ins get priority over map attributes in an access like this.

The updated code to handle this case would use ["attr"] based access. This session in the REPL shows more:

Risor

>>> issues := {"items": [1,2,3]}
>>> issues
{"items": [1, 2, 3]}
>>> issues.items
builtin(map.items)
>>> issues.items()
[["items", [1, 2, 3]]]
>>> issues['items']
[1, 2, 3]
>>> 

I was a bit worried when I added map item access using .attr because of the potential for this confusion.

myzie commented 1 week ago

Improving the to-string formatting to show something more useful in the case you reported initially would be one way to make this a bit better.