Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow encoding literal JSON values #2041

Merged
merged 31 commits into from
Oct 21, 2022
Merged

Conversation

aSemy
Copy link
Contributor

@aSemy aSemy commented Sep 22, 2022

This PR provides a new function for encoding raw JSON content, without quoting it as a string. This allows for encoding JSON numbers of any size or precision, so BigDecimal and BigInteger can be supported.

Link to view the updated documentation

fix: #1051
fix: #1405

related:

The implementation is similar to how unsigned numbers are handled.

  • JsonUnquotedLiteral() is a new function that allows creating literal JSON content.
  • I added val coerceToInlineType to JsonLiteral, so that JsonUnquotedLiteral could use encodeInline()
  • I defined val jsonUnquotedLiteralDescriptor as a 'marker', for use with encodeInline()
  • ComposerForUnquotedLiterals (based on ComposerForUnsignedNumbers) will 'override' the encoder when a JsonLiteral has the jsonUnquotedLiteralDescriptor marker, and will encode the content as a string without surrounding quotes.

I'm not sure how to proceed with decoding literal numbers. I just realised, there's no need for special implementation - primitives are all decoded the same.

@aSemy aSemy marked this pull request as ready for review September 22, 2022 21:51
@aSemy
Copy link
Contributor Author

aSemy commented Sep 22, 2022

I think more tests and specialist knowledge is needed, but the approach is ready for review. I'm really keen to provide a way of supporting BigDecimal, as it's been a blocker in a couple of my projects for a long time.

Copy link

@YanishR YanishR left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When do you guys foresee there will be progress on this? I have a use case for it in my project

@sandwwraith
Copy link
Member

Hi, thanks for your PR! I think I have time for it on this week, stay tuned

@sandwwraith
Copy link
Member

I think we should have additional design discussion on a general approach (using encodeInline and JsonPrimitive(isString = true instead of a separate JsonEncoder.encodeUnquoted function); I'll keep you posted

Copy link
Member

@sandwwraith sandwwraith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a discussion, the following points were established:

  • Function should accept arbitrary strings and do not validate them with regex. This will allow users to do various json-embeddings, support non-base10 numbers, different notations, etc and will also simplify an invariant for users and save us from potential problems with regex correctness and performance.

  • Function should accept a String? and return JsonNull if a null was passed to it, for consistency with JsonPrimitive overloads.

  • However, if string literal "null" is passed (i.e. value == "null"), function should throw IllegalArgumentException. This is motivated by the fact that when we serialize such a literal, if effective becomes indistinguishable from JsonNull and can't be deserialized back to JsonLiteral. We cannot know for sure if this was a user intent to do so or bug in validation. Better to prohibit such cases. IAE message can sound like this: "It is impossible to create a literal unquoted value of 'null'. If you want to create json null literal, use JsonNull object, otherwise, use quoted literal."

Summarising this all up, I suggest to name the new function 'JsonUnquotedPrimitive'. What do you think?

@aSemy aSemy changed the title allow encoding literal JSON numbers allow encoding literal JSON values Oct 12, 2022
@sandwwraith
Copy link
Member

Also, I've just noted that the PR is opened against master branch, while all new PRs with code should be opened against dev. Can you change the branch please?

@aSemy aSemy changed the base branch from master to dev October 13, 2022 13:03
@aSemy
Copy link
Contributor Author

aSemy commented Oct 13, 2022

I've updated the PR to point at dev, and merged dev into this branch, but it looks like dev is missing commits from master. Can master be merged into dev?

@sandwwraith
Copy link
Member

dev is missing commits from master. Can master be merged into dev?

That's a normal situation. We only merge master into dev before the actual release

@aSemy aSemy force-pushed the feat/1051-big_decimals branch from 2d1e859 to ff8fd99 Compare October 13, 2022 14:35
Copy link
Member

@sandwwraith sandwwraith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job, thanks for implementing this important feature!

@sandwwraith sandwwraith merged commit 46a5ff6 into Kotlin:dev Oct 21, 2022
@aSemy
Copy link
Contributor Author

aSemy commented Oct 21, 2022

Thanks! And thanks to you and @qwwdfsad for reviewing.

Do you know when this will be available? Does KxS have snapshot releases that I can use?

@sandwwraith
Copy link
Member

No, we don't usually publish snapshots. The next release is going to be around Kotlin 1.8.0 release, in a month or two

fred01 pushed a commit to fred01/kotlinx.serialization that referenced this pull request Nov 24, 2022
This PR provides a new function for encoding raw JSON content, without quoting it as a string. This allows for encoding JSON numbers of any size or precision, so BigDecimal and BigInteger can be supported.

Fixes Kotlin#1051
Fixes Kotlin#1405

The implementation is similar to how unsigned numbers are handled.

JsonUnquotedLiteral() is a new function that allows creating literal JSON content.
Added val coerceToInlineType to JsonLiteral, so that JsonUnquotedLiteral could use encodeInline()
Defined val jsonUnquotedLiteralDescriptor as a 'marker', for use with encodeInline()
ComposerForUnquotedLiterals (based on ComposerForUnsignedNumbers) will 'override' the encoder when a JsonLiteral has the jsonUnquotedLiteralDescriptor marker, and will encode the content as a string without surrounding quotes.
@aSemy aSemy deleted the feat/1051-big_decimals branch May 9, 2023 15:47
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.

How to serialize BigInteger and BigDouble?
4 participants