feat(http): support numeric field aliases in json parsing - #9
Open
waynercheung wants to merge 1 commit into
Open
waynercheung wants to merge 1 commit into
waynercheung wants to merge 1 commit into
Conversation
JsonFormat.mergeField resolves a single-digit key such as "2" to the field with that number, but then marked that field as unknown. For a message-typed field the flag made handleObject read the value as a hex-encoded protobuf message instead of parsing a JSON object, so the two spellings of one field accepted different syntaxes. Drop the flag and the hex branch so a single-digit alias is parsed by JsonFormat exactly like the field name, at any nesting level and for singular, repeated and map fields alike. The alias range is unchanged: only fields 1 to 9 can be addressed by number, and a key that resolves to no field is still skipped. Scalar and bytes aliases, unknown keys, null and empty arrays keep their current behaviour. This applies to protobuf fields only; the wallet endpoints still read raw_data, contract, parameter, value and type as literal JSON keys. Also compute the request url before the rate limiter checks in RateLimiterServlet, and pair the GET setup with the cleanup that follows it by wrapping both in the outer try, leaving the request handling in an inner try with the catch clauses it already had. BREAKING CHANGE: a message-typed field addressed by its field number now accepts JSON objects instead of hex-encoded protobuf strings. Direct JSON-to-protobuf merges reject the old string form with a parse error. During per-contract parsing, Util.packTransaction omits contracts that fail to parse; remaining contracts continue through normal endpoint validation, and if none remain the endpoint's existing empty-contract handling applies. Parse errors during the final transaction merge instead make Util.packTransaction return null, invoking the caller's existing error handling. JSON-RPC ABI parsing rejects this form with "invalid abi". Clients using numeric aliases should send the same JSON objects they would send for field names.
rmoozy77729-maker
approved these changes
Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
JsonFormat.mergeFieldresolves a single-digit JSON key such as"2"to the field with that number when the name lookup fails, but it then marked that field as unknown. For a message-typed field the flag madehandleObjectread the value as a hex-encoded protobuf message instead of parsing a JSON object, so the two spellings of one field accepted different syntaxes:{"owner":{"keys":[{}]}}{"2":{"keys":[{}]}}Expected string.{"2":"3a00"}Expected "{".{"2":["3a00"]}/{"owner":{"7":"1001"}}{"1":"<address>"},{"2":null},{"2":[]}This PR drops the flag and the hex branch, together with the parameters, import and comment that become dead, so a numeric alias goes through the same object parser as the field name at any nesting level and for singular, repeated and map fields alike.
Scope is unchanged: only fields 1 to 9 can be addressed by number (
DIGITSmatches a single character), and a key that resolves to no field is still skipped. Scalar and bytes aliases, unknown keys,nulland empty arrays keep their current behaviour. This applies to protobuf fields only; the wallet endpoints still readraw_data,contract,parameter,valueandtypeas literal JSON keys.The commit also reorders a few statements in
RateLimiterServlet.service: the request url is computed before the rate limiter checks, and the GET setup is paired with the cleanup that follows it by wrapping both in the outer try, leaving the request handling in an inner try with the catch clauses it already had.Why are these changes required?
One field had two different input syntaxes depending on how it was spelled, and the hex form is an artifact of the
protobuf-java-formatcode this class was forked from in 2018: the node never emits it (unknown fields are not printed), no in-repo caller produces it, andcom.google.protobuf.util.JsonFormathas no equivalent. Making both spellings parse the same way removes the divergence and keeps numeric aliases usable in the form clients would expect.BREAKING CHANGE
A message-typed field addressed by its field number now accepts JSON objects instead of hex-encoded protobuf strings:
Util.packTransactionomits contracts that fail to parse, the remaining contracts continue through normal endpoint validation, and if none remain the endpoint's existing empty-contract handling applies;Util.packTransactionreturn null, invoking the caller's existing error handling;invalid abi.Clients using numeric aliases should send the same JSON objects they would send for field names. During a rolling upgrade, use field names.
This PR has been tested by:
JsonFormatNumericAliasTest(new, 23 cases) covers alias-equals-name for singular, repeated, nested, map and map-entry fields,visible=trueaddress and name-string bytes, enum by field and value in both spellings,null/[]/{}, rejection of the string form in every position, the single-digit range boundary, mixed name-and-alias documents, and partial state after a failed element.UtilTestadds 4 cases forUtil.packTransaction(alias equivalence, dropped contract, only-the-failing-contract dropped, envelope-level failure returning null),JsonrpcServiceTestadds 2 for the JSON-RPC ABI path, andRateLimiterServletTestadds 2.Targeted run on JDK 17:
JsonFormatNumericAliasTest23,JsonFormatTest27,JsonFormatEscapeTest33,JsonFormatInt64AsStringTest13,UtilTest10,RateLimiterServletTest14,RateLimiterServletInt64Test6,JsonrpcServiceTest30 — 156 tests, 0 failures.checkstyleMainandcheckstyleTestclean.Follow up
None.
Extra details
Behaviour verified against the base build for every case above: 16 of the 23 new parser tests fail without this change, and the 7 that pass are the invariant guards for the behaviours listed as unchanged.