itchyny / gojq

Pure Go implementation of jq
MIT License
3.3k stars 119 forks source link

Duplicate keys in object literals have inconsistent behavior #238

Closed SOF3 closed 9 months ago

SOF3 commented 9 months ago

This behavior is slightly different from the C jq (jq-1.7).

$ jq --version
jq-1.7

$ gojq --version
gojq 0.12.13 (rev: HEAD/go1.20)

$ jq -n '{a: 1, a: {b}}'
{
  "a": {
    "b": null
  }
}

$ gojq -n '{a: 1, a: {b}}'
{
  "a": 1
}

However, gojq is consistent with jq-1.7 if I write a: {}, a: {b: "b"}, a: {b: null}, etc instead.

I also reproduced this case with a non-null expression, but I cannot provide the exact reproducible case since that query contains something personal, and I am unable to reduce the other case into an {"a": 1} output.

SOF3 commented 9 months ago
$ gojq -n '{a: 1, a: {b}}'
{
  "a": 1
}

$ gojq -n '{a: 1, a: {b: .b}}'
{
  "a": 1
}

$ gojq -n '{a: 1, a: {b: {c}}}'
{
  "a": 1
}

$ gojq -n '{a: 1, a: {b: length}}'
{
  "a": 1
}

$ gojq -n '{a: 1, a: {b: null}}'
{
  "a": {
    "b": null
  }
}

$ gojq -n '{a: 1, a: {}}'
{
  "a": {}
}
SOF3 commented 9 months ago

Based on the above experiments, my hypothesis that gojq uses the latter value if it is a pure literal, and uses the former value if the latter expression involves any dynamically resolved data.

itchyny commented 9 months ago

It seems that I didn't expect this case when implemented the executor but I'll fix soon. Constant folding makes it working correctly.

SOF3 commented 9 months ago

Haven't had time to reduce a minimal reproducible example yet, but I think there is another similar issue with the order of object keys as well; I just reproduced a case where gojq does not correctly preserve object key order when adding two objects, while jq does it correctly.