swift-extras / swift-extras-json

JSON encoding and decoding without the use of Foundation in pure Swift.
Apache License 2.0
348 stars 15 forks source link

Why does use of this API require conformance to Encodable? #64

Open brianreinhold opened 4 years ago

brianreinhold commented 4 years ago

I thought the whole point of this library was that one DIDN'T need to use Encodable and Decodable? I am trying desperately to solve the problem of precision in floating point numbers and its the Encodable/Decodable requirement is the cause of the problem.

How would I encode a struct like this (with some values of course)

struct TestIt { var title: String var value: Float }

to a JSON String that can be sent on the wire without specifying conformance to Encodable?

fabianfett commented 4 years ago

Hi @brianreinhold, thanks for bringing this up:

I thought the whole point of this library was that one DIDN'T need to use Encodable and Decodable?

The point of the library is to create an alternative to JSONEncoder and JSONDecoder from Foundation. Since the encoder and decoder work with the Codable protocol, my implementation does the same. (Though faster!)

How would I encode a struct like this (with some values of course)

You could manually create a JSONValue from your structure.

See https://github.com/fabianfett/pure-swift-json/blob/main/Sources/PureSwiftJSON/JSONValue.swift

If you want to encode this structure you can:

let value: JSONValue = .object([
  "title": .string("foo bar"),
  "value": .number("1.000")
])

var result = [UInt8]()
value. appendBytes(to: result)

Since the numbers are encoded internally as a string you will continue to have the decimal precision. Does this fix your problem?

brianreinhold commented 4 years ago

YESSS!!! 💗💗💗💗💗😊😊😊😊

Brian


From: Fabian Fett notifications@github.com Sent: Sunday, September 13, 2020 11:45 AM To: fabianfett/pure-swift-json pure-swift-json@noreply.github.com Cc: Brian Reinhold BrianReinhold@lnihealth.com; Mention mention@noreply.github.com Subject: Re: [fabianfett/pure-swift-json] Why does use of this API require conformance to Encodable? (#64)

Hi @brianreinholdhttps://github.com/brianreinhold, thanks for bringing this up:

I thought the whole point of this library was that one DIDN'T need to use Encodable and Decodable?

The point of the library is to create an alternative to JSONEncoder and JSONDecoder from Foundation. Since the encoder and decoder work with the Codable protocol, my implementation does the same. (Though faster!)

How would I encode a struct like this (with some values of course)

You could manually create a JSONValue from your structure.

See https://github.com/fabianfett/pure-swift-json/blob/main/Sources/PureSwiftJSON/JSONValue.swift

If you want to encode this structure you can:

let value: JSONValue = .object([ "title": .string("foo bar"), "value": .number("1.000") ])

var result = [UInt8]() value. appendBytes(to: result)

Since the numbers are encoded internally as a string you will continue to have the decimal precision. Does this fix your problem?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/fabianfett/pure-swift-json/issues/64#issuecomment-691687899, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJMDO67JKNHUUS46XNNDAETSFTSJPANCNFSM4RISIVLA.

fabianfett commented 4 years ago

Great, can this issue be closed?

brianreinhold commented 4 years ago

Fabian,

Is there a way to 'pretty print' the output? The JSONValue does not comply to Codable so I could not use the JSONEncoder() on the string or byte array generated by JSONValue. THis is not critical but it would be nice if one could.

Brian


From: Fabian Fett notifications@github.com Sent: Monday, September 14, 2020 3:31 AM To: fabianfett/pure-swift-json pure-swift-json@noreply.github.com Cc: Brian Reinhold BrianReinhold@lnihealth.com; Mention mention@noreply.github.com Subject: Re: [fabianfett/pure-swift-json] Why does use of this API require conformance to Encodable? (#64)

Great, can this issue be closed?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/fabianfett/pure-swift-json/issues/64#issuecomment-691875285, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJMDO64QWKHCO7VZ5J6HGO3SFXBGFANCNFSM4RISIVLA.

fabianfett commented 4 years ago

@brianreinhold sadly there is none at the moment, but I'd be happy to review a pr that addresses this shortcoming.

brianreinhold commented 4 years ago

Fabian,

That's not really important; there are plenty of JSON formatters on line one can use for displaying a JSON string

What I have been trying to is to make a custom data type (struct) 'Codable' so that one could the PSEncoder() method and not have to use the low level JSONValue() methods, etc. I have co workers that will complain - but in the end, we MUST have precision so given no easier alternative we will do it.

I looked through your code and basically made the effort to add new 'encode' methods to handle this data type but they never get called. Stepping through with a debugger it looks like JSONEncoderImpl ends up calling Swift library functions.

Basically what I am trying to do is take that MderFloat struct and make it Encodable so it looks like a primitive in any other object that uses it. Maybe its not possible without modification of Apple source code.

Brian


From: Fabian Fett notifications@github.com Sent: Monday, September 14, 2020 7:04 AM To: fabianfett/pure-swift-json pure-swift-json@noreply.github.com Cc: Brian Reinhold BrianReinhold@lnihealth.com; Mention mention@noreply.github.com Subject: Re: [fabianfett/pure-swift-json] Why does use of this API require conformance to Encodable? (#64)

@brianreinholdhttps://github.com/brianreinhold sadly there is none at the moment, but I'd be happy to review a pr that addresses this shortcoming.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/fabianfett/pure-swift-json/issues/64#issuecomment-691981994, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJMDO65AGKKATJHK7TPE7ZTSFX2FXANCNFSM4RISIVLA.

fabianfett commented 4 years ago

What you're trying to achieve is possible, but it won't work with Apples encoder anymore and you'll need to copy and paste my encoder into your code base to make those adjustments. Would you mind sharing your Float type here?

brianreinhold commented 4 years ago

Fabian,

I have already done that. I copied all your source files to a simple project to learn how to use it. I am a total newbie to Apple and Swift so there are a lot of things that are still confusing about the language, XCode, and Apple.

The MderFloat is an IEEE medical device specification for float values that carry precision. It's quite simple; it contains an exponent and mantissa where both the mantissa and exponent are always signed integers. The 'float value' is given by mantissa * 10**exponent. But there are rules. The mantissa gives the number of significant figures and the exponent gives precision. Basically, the exponent tells you where to put the decimal point in the mantissa. So a mantissa of 2000 and an exponent of -3 gives 2.000. IN Java, my MderFloat class had a method that created the correctly formatted string from the MderFloat primitives. This would be placed in HL7 FHIR and V2 messages.

So in your three JSONUnkeyd..., JSONKeyed ..., and JSONSingle.... files I added extra encoders for the MderFloat 'data' type. However, they never get called.

I am practicing with a very simple test version of the MderStruct (with no error checking, etc.) just to get the basics. Cleanup later.

struct MderFloat { var exponent Int var mantissa Int init (exponent: Int, mantissa: Int) { self.mantissa = mantissa self.exponent = exponent } }

Then I make a simple struct

struct TestIt { var title: String var mderFloat: MderFloat }

One thing that might indicate success is if I dont have to put :Codable on the MderFloat struct....

Brian


From: Fabian Fett notifications@github.com Sent: Monday, September 14, 2020 8:06 AM To: fabianfett/pure-swift-json pure-swift-json@noreply.github.com Cc: Brian Reinhold BrianReinhold@lnihealth.com; Mention mention@noreply.github.com Subject: Re: [fabianfett/pure-swift-json] Why does use of this API require conformance to Encodable? (#64)

What you're trying to achieve is possible, but it won't work with Apples encoder anymore and you'll need to copy and paste my encoder into your code base to make those adjustments. Would you mind sharing your Float type here?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/fabianfett/pure-swift-json/issues/64#issuecomment-692009572, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJMDO663M2AZRP3WOE557MLSFYBN3ANCNFSM4RISIVLA.