Skip to content

fix(json): preserve empty arrays across decode + re-encode#207

Open
AlinsRan wants to merge 1 commit into
bungle:masterfrom
AlinsRan:fix/json-empty-array-array-mt
Open

fix(json): preserve empty arrays across decode + re-encode#207
AlinsRan wants to merge 1 commit into
bungle:masterfrom
AlinsRan:fix/json-empty-array-array-mt

Conversation

@AlinsRan

Copy link
Copy Markdown

Summary

The private cjson instance in lib/resty/session/utils.lua (shared by encode_json/decode_json) decodes JSON without the array metatable. As a result an empty JSON array ([]) loses its array-ness on decode and is re-encoded as an object ({}).

Any session payload that carries an empty array therefore has it silently mutated from [] to {} after a save → load → save round-trip. This surfaced downstream in APISIX's openid-connect plugin: an empty array claim in the OIDC userinfo (e.g. empty groups/roles) comes back as {}, breaking backends that expect an array (apache/apisix#13440). It is a regression since the private cjson instance was introduced.

Fix

Enable decode_array_with_array_mt(true) on the instance when it is created, so decoded arrays keep the array metatable and round-trip correctly. encode_json and decode_json share the same lazily-created instance, so the option is set at whichever creation site runs first.

Behavior verified:

default:               {"items":[]} -> decode -> encode -> {"items":{}}
decode_array_with_array_mt(true):  {"items":[]} -> decode -> encode -> {"items":[]}

Non-empty arrays already round-tripped correctly (cjson infers an array from the elements); only empty arrays were affected, and objects are unchanged.

Test

Added a regression test in spec/01-utils_spec.lua that decodes {"items":[]} and asserts it re-encodes back to {"items":[]} (fails before the change, passes after).

The shared private cjson instance in utils.lua decoded JSON without the array
metatable, so an empty array (`[]`) lost its array-ness and was re-encoded as
an object (`{}`). Sessions that carry an empty array (e.g. an OIDC userinfo
claim) thus had it silently turn into `{}` after a save/load round-trip.

Enable decode_array_with_array_mt(true) on the instance at creation so decoded
arrays keep the array metatable and round-trip correctly. Added a regression
test in spec/01-utils_spec.lua.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant