Skip to content

Instantly share code, notes, and snippets.

@magicien
Created August 22, 2017 11:44
Show Gist options
  • Save magicien/3f749a82688ab9ad3e4fa6afae6bbe82 to your computer and use it in GitHub Desktop.
Save magicien/3f749a82688ab9ad3e4fa6afae6bbe82 to your computer and use it in GitHub Desktop.
import Foundation
// framework側のコード
let ExtensionKey = CodingUserInfoKey(rawValue: "extensionKey")!
struct Group: Codable {
let users: [User]
}
struct User: Codable {
let name: String
let additionalInfo: ExtensibleJSON?
enum CodingKeys: String, CodingKey {
case name
case additionalInfo = "additional_info"
}
}
struct ExtensibleJSON: Codable {
var extensions: [String:Codable] = [:]
init(from decoder: Decoder) throws {
if let extensions = decoder.userInfo[ExtensionKey] as? [String:Codable.Type] {
for (key, ExtensionCodable) in extensions {
self.extensions[key] = try ExtensionCodable.init(from: decoder)
}
}
}
func encode(to encoder: Encoder) throws {
// do something
}
}
public class ExtensibleJSONUnarchiver {
let group: Group
public init(data: Data, extensions: [String:Codable.Type]? = nil) throws {
let decoder = JSONDecoder()
decoder.userInfo[ExtensionKey] = extensions
self.group = try decoder.decode(Group.self, from: data)
}
}
// ユーザ側のコード
let json = """
{
"users": [
{
"name": "userA",
"additional_info": {
"special_info": {
"foo": "bar"
},
"website": {
"name": "DarkHorse",
"url": "http://darkhorse2.0spec.jp"
},
}
},
{
"name": "userB"
},
{
"name": "userC",
"additional_info": {}
},
{
"name": "userD",
"additional_info": {
"website": {
"name": "Gist",
"url": "https://gist.github.com/"
},
"other_info": {}
}
}
]
}
""".data(using: .utf8)!
var userWebsites = [String:URL]()
struct WebsiteExtension: Codable {
struct Website: Codable {
enum CodingKeys: String, CodingKey {
case name
case url
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let name = try container.decode(String.self, forKey: .name)
let url = try container.decode(URL.self, forKey: .url)
userWebsites[name] = url
}
func encode(to encoder: Encoder) throws {
// do something
}
}
let website: Website?
}
do {
let extensions: [String:Codable.Type] = [
"website": WebsiteExtension.self
]
let unarchiver = try ExtensibleJSONUnarchiver(data: json, extensions: extensions)
for (name, url) in userWebsites {
print("\(name): \(url)")
}
} catch DecodingError.keyNotFound(let key, let context) {
print("keyNotFound: \(key): \(context)")
} catch {
print("\(error.localizedDescription)")
}
/*
Gist: https://gist.github.com/
DarkHorse: http://darkhorse2.0spec.jp
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment