Argo icon indicating copy to clipboard operation
Argo copied to clipboard

Rename JSON to Value

Open gfontenot opened this issue 6 years ago • 18 comments

We're going to be shifting the marketing focus for Argo away from being a JSON parser and towards being a general purpose parser for transforming loosely typed data models into strongly typed ones. As a part of this change, we can generalize our types a bit, and use the name Value for our input values, instead of JSON. This change is purely cosmetic, but will result in a more general API, letting us break a bit from our ties to JSON.

Note that we're providing a typealias from JSON to Value here as well. This should make this a non-breaking change (although users will get a deprecation warning). I'd love it if other people could test this with their codebase.

gfontenot avatar Sep 30 '17 16:09 gfontenot

This should make this a non-breaking change (although users will get a deprecation warning).

There's a caveat here: this isn't a source breaking change, but it is a binary breaking change.

mdiep avatar Oct 03 '17 00:10 mdiep

It would be versioned, so how is that relevant?

jshier avatar Oct 03 '17 00:10 jshier

We ran into an issue with this with ReactiveCocoa or ReactiveSwift. I can't find the specific GitHub issue, but @andersio or @ikesyo might remember how to find it.

IIRC, it becomes an issue if frameworks are compiled against different versions of Argo.

Imagine you have A.framework and B.framework. Both A and B have declared that they're compatible with Argo 4.1..<5.0. When you compile A, it uses Argo 4.1. When you compile B, it uses a copy of Argo, say 4.2, that includes this change. The compiled versions of A and B cannot be used together.

This will lead to build failures when using Carthage in many cases. (Depending on how A and B are set up.) I'm unsure whether this is a problem in practice with CocoaPods or SwiftPM. Semantic version unfortunately doesn't really address the difference between source compatibility and binary compatibility—that's part of the reason I don't think we should use semver.

mdiep avatar Oct 03 '17 06:10 mdiep

This would only really be an issue if we didn't release this as 5.0, right? I was assuming that the rename changes would come with a 5.0 label because I do see binary breakage as being a breaking change.

gfontenot avatar Oct 03 '17 13:10 gfontenot

@mdiep I'm not really sympathetic to that scenario. If you're not properly managing your versions, or you're distributing third party libraries precompiled, it's up to you, not the library, to ensure the versions work together. It's the same reason we don't distribute static Alamofire libraries: we don't want to be bound by whatever binary issues may ensue. To me it's only valid to consider the binary compatibility of libraries that are actually distributed as binaries. Especially until Swift has an actual ABI. At that point managing binary compatibility becomes much much easier.

jshier avatar Oct 03 '17 15:10 jshier

This would only really be an issue if we didn't release this as 5.0, right? I was assuming that the rename changes would come with a 5.0 label because I do see binary breakage as being a breaking change.

Correct. I only brought it up since you mentioned this was a non-breaking change and this previously caught me be surprise. ☺️

If you're not properly managing your versions, or you're distributing third party libraries precompiled, it's up to you, not the library, to ensure the versions work together.

This isn't about distributing precompiled libraries. It's noting that "breaking change" according to SemVer doesn't distinguish between source-breaking and binary-breaking.

A common way this might arise: A framework includes its dependencies as submodules and builds against the submodule versions. These aren't precompiled. They're just a different version than the one you might ultimately link against.

mdiep avatar Oct 03 '17 16:10 mdiep

Submodule integration, unless managed by a tool, falls under the "not properly managing your versions" umbrella. To my mind, libraries aren't responsible for version conflicts in a non-version managed environment. Frankly I think SemVer doesn't mention binary compatibility because it assumes ABI stability on the part of the language itself. Swift is rather unusual in that case and the concern will go away after Swift 5.

jshier avatar Oct 03 '17 17:10 jshier

Submodule integration, unless managed by a tool, falls under the "not properly managing your versions" umbrella.

These submodules can be managed by Carthage.

Frankly I think SemVer doesn't mention binary compatibility because it assumes ABI stability on the part of the language itself

I'm not sure those are the same thing. AIUI ABI stability guarantees compatibility between different versions of the compiler, which is not necessarily the same thing as guaranteeing that a source-compatible change is always a binary-compatible change. (As evidenced by the fact that this problem occurs when using the same version of swift for all dependencies.)

Frankly I think SemVer doesn't mention binary compatibility because it assumes ABI stability on the part of the language itself.

I think the more likely explanation is that Tom Preston-Werner (SemVer's author) is primarily experienced in Ruby and JavaScript. ☺️

mdiep avatar Oct 03 '17 23:10 mdiep

7 months seems like it's long enough to wait for feedback on a change like this, right? Any last-minute objections?

gfontenot avatar Apr 25 '18 20:04 gfontenot

Given that the Swift team seems to see no importance in being able to decode anything but Data, has thought been given to how this change, or Argo in general, could be used as a Codable wrapper for Any and such? Or is that planned already?

jshier avatar Apr 25 '18 21:04 jshier

I don't think I've put much thought into Codable for Any at all, but I do think it's worth re-framing Argo as a more generic library for converting from weakly typed data structures into strongly typed ones. That sure sounds like what you're describing though.

gfontenot avatar Apr 25 '18 21:04 gfontenot

Yes. There's been some discussion on the Swift forum regarding how to handle unstructured values in regards to decoding JSON (and like other decoding situations). Some users had created a JSON enum almost exactly like Argo, and I think someone had made Argo's JSON Decodable as well. It would be nice if the new Argo Value type could fill that niche OOTB.

jshier avatar Apr 25 '18 21:04 jshier

Oh, I like AnyValue. My brain thinks of Any* types to be type erasers, though, where as this is more of a type... pencil? What's the dual of a type eraser? Identifier?

gfontenot avatar Apr 26 '18 15:04 gfontenot

@jshier I dig the direction you're going, fwiw. I don't want to derail this conversation though. Want to open a new issue with a proposal (if you have one, or a basic discussion starter if you don't)? It seems like this might dovetail with #481, too.

gfontenot avatar Apr 26 '18 15:04 gfontenot

My brain thinks of Any* types to be type erasers, though

Yeah, I'm not sure AnyValue is quite right. Although I do think it would read nicely at the point of use:

static func decode(_ v: AnyValue) -> Decoded<Foo> {
  // ...
}

Things I like about it:

  • Communicates that the thing you have has a weaker type than the thing you want
  • Succinct
  • Idiomatic

Possible concerns:

  • It's not really a type eraser
  • Possibly implies that you can dynamic cast, which is true for things typed Any, AnyHashable and AnyKeyPath (but is not true for AnySequence or AnyCollection)

sharplet avatar Apr 26 '18 16:04 sharplet

It's also not "Any" value but a limited subset of values. Even if the supported types expand beyond the current design, "Any" will always be a bit misleading.

jshier avatar Apr 26 '18 16:04 jshier

It's also not "Any" value but a limited subset of values.

IMO the idea is less that it could be any value, and more that it's a valid in-memory encoding of any value.

sharplet avatar Apr 26 '18 16:04 sharplet

Would it make sense to be generic over some Value type instead?

JSON really is JSON-specific. You might want to work with a different set of primitive types. e.g. if you wanted to work with a plist, you might add date and data and rename object to dictionary. JSON could be left as-is to support JSON out-of-the-box.

That would also require adding format-specific Decodable protocols, which is a little bit of a pain, but not too bad.

mdiep avatar Apr 29 '18 20:04 mdiep