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

[SR-5784] JSONEncoder is lossy for URL type #4075

Open
swift-ci opened this issue Aug 28, 2017 · 5 comments
Open

[SR-5784] JSONEncoder is lossy for URL type #4075

swift-ci opened this issue Aug 28, 2017 · 5 comments
Assignees

Comments

@swift-ci
Copy link
Contributor

Previous ID SR-5784
Radar rdar://problem/34138907
Original Reporter ylin (JIRA User)
Type Bug
Environment

macOS, Swift 4 08-21 snapshot

Additional Detail from JIRA
Votes 0
Component/s Foundation
Labels Bug
Assignee @itaiferber
Priority Medium

md5: e6d42a434f747ae22d710ada3ecdf7b6

Issue Description:

While playing around JSONEncoder/JSONDecoder, I found that the `URL` type is lossy on encode -> decode.

Example:

ylin@youming-mbpr:~/Swift/Configuration$ swift
Welcome to Apple Swift version 4.0-dev (LLVM 2dedb62a0b, Clang b9d76a314c, Swift 61ad3c07ef). Type :help for assistance.
  1> import Foundation 
  2. let url = URL(string: "../", relativeTo: URL(string: "http://example.com/test"))! 
  3. let url2 = JSONDecoder().decode([URL].self, from: JSONEncoder().encode([url]))[0] 
  4. url == url2
$R0: Bool = false
url: URL = "../ -- ttp://example.com/test"
url2: URL = "http://example.com/../"

The same URL is read back losslessly using the `PropertyList` version, however:

ylin@youming-mbpr:~/Swift/Configuration$ swift
Welcome to Apple Swift version 4.0-dev (LLVM 2dedb62a0b, Clang b9d76a314c, Swift 61ad3c07ef). Type :help for assistance.
  1> import Foundation 
  2. let url = URL(string: "../", relativeTo: URL(string: "http://example.com/test"))! 
  3. let url2 = PropertyListDecoder().decode([URL].self, from: PropertyListEncoder().encode([url]))[0] 
  4. url == url2 
$R0: Bool = true
url: URL = "../ -- ttp://example.com/test"
url2: URL = "../ -- ttp://example.com/test"

Even more oddly, on Ubuntu 14.04 the same 08-21 snapshot produces the correct result:

ylin@ylin-VirtualBox:~$ swift -I/home/ylin/.swiftenv/versions/4.0-DEVELOPMENT-SNAPSHOT-2017-08-21-a/usr/lib/swift/clang/include
Welcome to Swift version 4.0-dev (LLVM 2dedb62a0b, Clang b9d76a314c, Swift 61ad3c07ef). Type :help for assistance.
  1> import Foundation 
  2. let url = URL(string: "../", relativeTo: URL(string: "http://example.com/test"))! 
  3. let url2 = JSONDecoder().decode([URL].self, from: JSONEncoder().encode([url]))[0] 
  4. url == url2
$R0: Bool = true
url: Foundation.URL = <redacted>
url2: Foundation.URL = <redacted>
@belkadan
Copy link

cc @itaiferber

@itaiferber
Copy link
Contributor

This is actually done on purpose — overall, it would be significantly more surprising to people if {{URL}}s they got from potentially arbitrary sources encoded as a dictionary instead of as a string. We encode {{URL}}s as absolute strings because most consumers of JSON would expect that; unfortunately, it means that we lose the relativeness.

We can potentially add a strategy to tell JSONEncoder to preserve the structure as-is for round-tripping.

The Linux behavior can actually be considered a bug; it will be fixed once PR-11315 is pulled into a Swift release.

@itaiferber
Copy link
Contributor

@swift-ci Create

@swift-ci
Copy link
Contributor Author

Comment by Youming Lin (JIRA)

@itaiferber Thanks for the explanation. And +1 on the new option; I could see this being used for debug logging in JSON format, in which case a lossless archival of the object state might be beneficial.

Also, for future reference, are there any other native/Foundation types that aren't losslessly encoded by JSONEncoder?

@itaiferber
Copy link
Contributor

ylin (JIRA User) There shouldn't be, no. All other types which have multiple potential representations encode as a dictionary; URL is just unique in that most consumers of the JSON would be expecting a string, so we do this for maximum compatibility.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants