我一直在玩,Codable并从文件中读取和写入JSON.现在我想写一个Coder可以读写iOS .strings文件的自定义.谁能帮我这个?我发现协议Encoder和Decoder,但我不知道我应该实现此:
class StringsEncoder {}
extension StringsEncoder: Encoder {
var codingPath: [CodingKey?] {
return []
}
var userInfo: [CodingUserInfoKey : Any] {
return [:]
}
func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
}
func unkeyedContainer() -> UnkeyedEncodingContainer {
}
func singleValueContainer() -> SingleValueEncodingContainer {
}
}
extension StringsEncoder: Decoder {
func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {
}
func unkeyedContainer() throws -> …Run Code Online (Sandbox Code Playgroud) 我目前正在处理Codable项目中的类型并遇到问题.
struct Person: Codable
{
var id: Any
}
Run Code Online (Sandbox Code Playgroud)
id在上面的代码中可以是a String或an Int.这就是id类型的原因Any.
我知道Any不是Codable.
我需要知道的是我如何才能使它发挥作用.
我正在使用Swift 4和Xcode 9.2编写程序.我在编写可编码类(完全是类,而不是struct)时遇到了困难.当我尝试从另一个类继承一个类时,JSONEncoder不从子类(子)获取所有属性.请看这个:
class BasicData: Encodable {
let a: String
let b: String
init() {
a = "a"
b = "b"
}
}
class AdditionalData: BasicData {
let c: String
init(c: String) {
self.c = c
}
}
let encode = AdditionalData(c: "c")
do {
let data = try JSONEncoder().encode(encode)
let string = String(data: data, encoding: .utf8)
if let string = string {
print(string)
}
} catch {
}
Run Code Online (Sandbox Code Playgroud)
它会打印出来: {"a":"a","b":"b"}
但我需要这个: {"a":"a","b":"b","c":"c"}
它看起来像c类的属性AdditionalData只是失去了某处,不知何故.
所以问题是:如果我有使用协议编码的类Encodable如何正确地创建子类(此类的子类,继承)类?
我会感谢任何帮助或建议.
我正在尝试通过符合Encodable协议的编码模型获取数据.但它无法encode像下面的代码那样调用func :
// MARK: - Demo2
class TestClass2: NSObject, Encodable {
var x = 1
var y = 2
}
var dataSource2: Encodable?
dataSource2 = TestClass2()
// error: `Cannot invoke 'encode' with an argument list of type '(Encodable)'`
let _ = try JSONEncoder().encode(dataSource2!)
//func encode<T>(_ value: T) throws -> Data where T : Encodable
Run Code Online (Sandbox Code Playgroud)
但在另一个演示中,它运作良好,为什么?
// MARK: - Demo1
protocol TestProtocol {
func test()
}
class TestClass1: NSObject, TestProtocol {
func test() {
print("1")
}
var …Run Code Online (Sandbox Code Playgroud) 我有一个带有 2 个符合它的结构的 Animal 协议和一个存储动物列表的 Farm 结构。然后,我让它们都符合 Codable 将其存储在一个文件中,但它抛出了错误cannot automatically synthesize 'Encodable' because '[Animal]' does not conform to 'Encodable'
我明白为什么会发生这种情况,但我找不到好的解决方案。我怎样才能让数组只接受 Codable 和 Animal,而不将 Animal 标记为 Codable 所以这个问题不会发生,比如var animals = [Codable & Animal]?(或任何其他变通方法)。谢谢
protocol Animal: Codable {
var name: String { get set }
var sound: String { get set }
}
struct Cow: Animal {
var name = "Cow"
var sound = "Moo!"
}
struct Duck: Animal {
var name = "Duck"
var sound = "Quack!"
} …Run Code Online (Sandbox Code Playgroud) 我想用 JSONEncoder 将字典编码为 json。它看起来像一个请求,接收一个字典作为参数并将其编码为 json 作为 http 正文。代码如下所示:
let dict = ["name": "abcde"]
protocol Request {
var params: [String: Encodable] { get set }
func encode<T>(_ value: T) throws -> Data where T : Encodable
}
extension Request {
func encode<T>(_ value: T) throws -> Data where T : Encodable {
return try JSONEncoder().encode(value)
}
var body: Data? {
if let encoded = try? self.encode(self.params) {
return encoded
}
return nil
}
}
struct BaseRequest: Request {
var params: [String …Run Code Online (Sandbox Code Playgroud) 我的应用程序使用一个返回 JSON 的服务器,如下所示:
{
"result":"OK",
"data":{
// Common to all URLs
"user": {
"name":"John Smith" // ETC...
},
// Different for each URL
"data_for_this_url":0
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,特定于 URL 的信息与通用user词典存在于同一词典中。
目标:
user很常见,我希望它位于顶级类/结构中。data从顶级user信息和子对象的信息重新创建字典)问题:
重新编码数据时,我无法将user字典(来自顶级对象)和特定于 URL 的数据(来自子对象)写入编码器。
要么user覆盖其他数据,要么其他数据覆盖user. 我不知道如何将它们结合起来。
这是我到目前为止所拥有的:
// MARK: - Common User
struct User: Codable {
var name: String?
}
// MARK: - Abstract Response
struct ApiResponse<DataType: Codable>: Codable …Run Code Online (Sandbox Code Playgroud) 想象一下一个数据结构,其中包含一个contents已经编码的JSON片段的值。
let partial = """
{ "foo": "Foo", "bar": 1 }
"""
struct Document {
let contents: String
let other: [String: Int]
}
let doc = Document(contents: partial, other: ["foo": 1])
Run Code Online (Sandbox Code Playgroud)
组合的数据结构应contents原样使用并编码other。
{
"contents": { "foo": "Foo", "bar": 1 },
"other": { "foo": 1 }
}
Run Code Online (Sandbox Code Playgroud)
Encodable以下Encodable编码实现Document为JSON,但是也将其重新编码contents为字符串,这意味着它被包装在引号中,并且所有"引号都转义为\"。
{
"contents": { "foo": "Foo", "bar": 1 },
"other": { "foo": 1 }
} …Run Code Online (Sandbox Code Playgroud) 我一直在寻找一种在结构中具有通用属性的方法,其中类型在运行时定义,例如:
struct Dog {
let id: String
let value: ??
}
Run Code Online (Sandbox Code Playgroud)
一个有用的简单用例是构建对象时json。Anode可以是int、string、bool、数组等,但除了类型可以改变之外,对象node保持不变。
经过一番思考并使用失败protocols(出现常见protocol 'X' can only be used as a generic constraint because it has Self or associated type requirements错误)后,我想出了两种不同的解决方案,#0 使用type erasure和 #1 使用type-erasureand generics。
#0(类型擦除)
struct AnyDog: Encodable {
enum ValueType: Encodable {
case int(Int)
case string(String)
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch …Run Code Online (Sandbox Code Playgroud) 鉴于课程:
class ComplementApp: Codable{
let name: String
let idSpring: String
}
class MasterClass: Encodable{
let complement: ComplementApp
///Other propierties
}
Run Code Online (Sandbox Code Playgroud)
我想得到:
//Where "Some ID" is the value of complement.idSpring
{
complement: "Some ID"
//Plus the other properties
}
Run Code Online (Sandbox Code Playgroud)
不是
{
complement: {
name: "Some Name",
idSpring: "Some ID"
}
//Plus other properties
}
Run Code Online (Sandbox Code Playgroud)
这是默认值。我知道我可以在 MasterClass 中抛出编码函数和 CodingKeys,但我还有 20 个其他变量,我应该添加 19 个额外的键。我可以在 ComplementApp 中实现 CodingKeys 来实现这一目标吗?
encodable ×10
swift ×9
codable ×7
decodable ×5
ios ×2
swift4 ×2
encoding ×1
generics ×1
inheritance ×1
json ×1
jsonencoder ×1
protocols ×1
struct ×1
type-erasure ×1