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

Expose an API to read primitive values of JSON keys as-is as a string #1557

Closed
nikolaykasyanov opened this issue Jun 15, 2021 · 3 comments
Closed
Labels

Comments

@nikolaykasyanov
Copy link

nikolaykasyanov commented Jun 15, 2021

What is your use-case and why do you need this feature?

The primary use case for this I have in mind is to be able to serialize numbers into types like BigInteger without loosing precision caused by currently unavoidable intermediate floating point number conversions.

This issue is the "read" counterpart of #1405.

At the moment, the only way I could find to achieve that is to set isLenient to true and use decodeString in KSerializer.deserialize implementations. This is unfortunately not acceptable because it requires enabling lenient parsing for the whole payload.

Another way is to have numbers serialized as strings but that's not always an option because 1) it might require changing already existing web APIs and 2) people don't always control APIs they have to deal with.

Describe the solution you'd like

From the top of my head, adding a mehod like to Decoder would do the trick:

fun decodeRawPrimitive(): String

This method would read a value as long as its primitive (number, bool, string) and return it as a string without any processing.

For example, reading the value of "name": "Joe" would return "\"Joe\"", reading "value": 0.43 would yield "0.43", reading "isExcited": true would yield "true".

If it encounters an object or array, it would throw, just like other decode<PrimitiveType> methods.

@pdvrieze
Copy link
Contributor

@nikolaykasyanov Looking at the library design I'm not sure how this would actually work. The problem with "raw" decoding is that it is inherently format specific. As an example, how would this work for protocol buffers or some other binary format? For some formats (like Android Parcelables) there are no delimiters/sizes so it is even impossible to read a "raw" value as you don't know its size.

In the case that you can control the on-the-wire format the solution is easy, use a custom serializer (for BigDecimal) to encode/decode to string rather than another value. It is also possible to special case specific formats in the serializer/deserializer although you should do so judiciously (with a generic fallback). What you really want is a format-specific way to handle the serialization of particular values in a "special" way. I would say that the solution would have to be some approach to register special casing to formats that get invoked based upon the registered serializer.

In summary:

  • Problem: Handle custom special serialization for particular types eg.: BigDecimal, UByteArray,...
  • Restriction: It should be flexible and not rely on hardcoding
  • Proposed solution direction: Formats to provide override hooks based upon serializer/serialname(of the type). These overrides aren't quite serializers as they would be having the specific format/encoder/decoder as parameter (and possibly ways to do format specific things such as reading raw values/bytes).

@nikolaykasyanov
Copy link
Author

@pdvrieze thank you very much for your input and the summary, I definitely didn't consider the full picture while writing this issue.

@sandwwraith
Copy link
Member

As #2041 shows, our Json lexer is very liberated in terms of quoting, so JsonDecoder.decodeJsonElement already can parse JsonLiteral from unquoted strings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants