Why are you stuck? I think the following matches your needs, no?
```swift
import Foundation
enum MyType : Codable, Equatable {
case int(Int)
case string(String)
case list([MyType])
case dictionary([String : MyType])
public init(from decoder: Decoder) throws {
// Can be made prettier, but as a simple example:
let container = try decoder.singleValueContainer()
do {
self = .int(try container.decode(Int.self))
} catch DecodingError.typeMismatch {
do {
self = .string(try container.decode(String.self))
} catch DecodingError.typeMismatch {
do {
self = .list(try container.decode([MyType].self))
} catch DecodingError.typeMismatch {
self = .dictionary(try container.decode([String :
MyType].self))
}
}
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .int(let int): try container.encode(int)
case .string(let string): try container.encode(string)
case .list(let list): try container.encode(list)
case .dictionary(let dictionary): try
container.encode(dictionary)
}
}
static func ==(_ lhs: MyType, _ rhs: MyType) -> Bool {
switch (lhs, rhs) {
case (.int(let int1), .int(let int2)): return int1 == int2
case (.string(let string1), .string(let string2)): return
string1 == string2
case (.list(let list1), .list(let list2)): return list1 ==
list2
case (.dictionary(let dict1), .dictionary(let dict2)): return
dict1 == dict2
default: return false
}
}
}
let values: MyType = .list([.int(42), .string("hello!"), .list([.int(9),
.string("hi")]), .dictionary(["zero": .int(0), "one": .int(1)])])
print(values)
let encoder = JSONEncoder()
let data = try encoder.encode(values)
print(String(data: data, encoding: .utf8)!) // =>
[42,"hello!",[9,"hi"],{"zero":0,"one":1}]
let decoder = JSONDecoder()
let decoded = try decoder.decode(MyType.self, from: data)
print(decoded)
print(values == decoded) // => true
```
On 19 Oct 2017, at 20:15, David Baraff wrote:
Begin forwarded message:
From: Itai Ferber <ifer...@apple.com>
Subject: Re: [swift-users] dealing with heterogenous lists/dictionary
with Codable
Date: October 19, 2017 at 9:39:25 AM PDT
To: David Baraff <davidbar...@gmail.com>
Cc: Geordie Jay <geo...@gmail.com>, swift-users
<swift-users@swift.org>
Hi David and Geordie,
That approach won’t work — encoders and decoders only work
directly with concrete Codable types (e.g. String, Int, MyFoo [where
MyFoo is Codable], etc.).
This is by design: since there is no type information stored in the
JSON payload, there isn’t necessarily a way to tell how to decode
the type you’re looking at, so asking for a generalCodable` isn’t
helpful.
Since it’s unlikely that what you truly need is a [String : Any]
but really a [String : <one of String, Int, MyFoo, etc.>], one easy
way to decode this type is to create a wrapper enum or similar which
overrides init(from:) to be able to decode from one of those types.
You can then ask to decode a [String : MyWrapperType] and use that
instead.
What types are you expecting in the dictionary?
The problem is that I want to be able to encode types T where
(a) T is String, Int
(b) lists of T
(c ) dictionaries of type <String, T>
The problem is the recursive nature: yes, my types are simple (say
only base types String and Int) but the “nesting” level may be
quite deep (a list of list of dictionaries of <etc.).
Let’s turn this around: in addition to the JSONEncoder, one can
also use the PropertyListEncoder.
Are we saying that something one could pull from a property list file
(which is pretty much what i want: arbitrary deep nesting of basic
types) is also not Codable? So a PropertyListEncoder could not encode
actual property lists?
I really do want a heterogenous container. I think I am stuck.
— Itai
On 19 Oct 2017, at 18:11, David Baraff via swift-users wrote:
I’ll try. Is that cast smart enough to apply recursively? We shall
see.
Sent from my iPad
On Oct 19, 2017, at 7:34 AM, Geordie Jay <geo...@gmail.com
<mailto:geo...@gmail.com>> wrote:
I mean can you do something along the lines of
let codableDict = stringAnyDict as? [String : Codable]
?
I’m not at a computer to test it myself
David Baraff <davidbar...@gmail.com <mailto:davidbar...@gmail.com>>
schrieb am Do. 19. Okt. 2017 um 15:45:
That’s exactly what I want. The ironic part is that I got my
dictionary by decoding a Json file. If that’s where my dictionary
came from, is there a simple way of coercing the Json serialization
routines to give me back codables, rather than Anys?
Sent from my iPad
On Oct 19, 2017, at 3:38 AM, Geordie Jay <geo...@gmail.com
<mailto:geo...@gmail.com>> wrote:
David Baraff via swift-users <swift-users@swift.org
<mailto:swift-users@swift.org>> schrieb am Do. 19. Okt. 2017 um
03:47:
So I have simple structs like this:
struct Library: Codable {
let domain: String
let unit: String
}
and it’s super-simple to serialize. Yay.
But:
struct LibraryGroup : Codable { // I wish...
let libraries: [Library]
let someDict: [String : Any]
}
I haven’t tried this, but is it possible to have a dictionary of
[String : Codable] ? Because that’s exactly the type requirements
you’re describing, no?
Geordie
So what I’m looking for is something where if the values in
someDict are themselves Codable, I can serialize things, and if
they’re not, I can’t. In my previous scheme, I was using
NSKeyedArchiver to serialize everything, manualy, including
someDict; in trying to switch to Codable I ran smack into the fact
that Codable wants to know what all the types are, in advance.
Am I just stuck? How do I get the best of both worlds, where the
compiler can make use of the fact that it can see the data types of
my structures, while still being able to serialize heterogenous
data like is found in LibraryGroup?
Is my only alternative to write a custom coder for LibraryGroup?
Is there any hope I could teach Codable what to do with
[String: Any]
?
_______________________________________________
swift-users mailing list
swift-users@swift.org <mailto:swift-users@swift.org>
https://lists.swift.org/mailman/listinfo/swift-users
<https://lists.swift.org/mailman/listinfo/swift-users>
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users
<https://lists.swift.org/mailman/listinfo/swift-users>
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users