将编码存储在Swift Dictionary中 [英] Store Encodables in a Swift Dictionary

查看:213
本文介绍了将编码存储在Swift Dictionary中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找将模型对象存储在字典中,并希望使用 JSONEncoder 将整个字典序列化为数据,然后将其保存到字符串中并保存。



这个想法是使用Swift 4开箱即用的 Encodable 来确保我添加到字典中的任何东西都会被序列化其中可以包含基元和自定义对象(它们本身将符合 Encodable )。

挑战是我应该声明字典的类型:


  • 如果我使用 [String:Any] ,它不知道如何编码 Any ,如果必须如果我使用 [String:Encodable] ,它会将其转换为实际的具体类型,这有点违背泛型的用途。会在运行时崩溃,说
    Encodable不符合自身,这是可以理解的,因为它
    需要一个具体类型


$ b $为了解决这个问题,我想创建一个包装器:
ie一个关联类型为的结构体,一个具有泛型类型值的结构体:

  struct Serializable< T:Encodable> {
var value:T?

init(value:T){
self.value = value
}
}

但是问题仍然存在,在声明上述字典的类型时,我仍然需要提供具体的类型..



< pre $ var字典:[String:Serializable< X>]

'X'应该在什么位置,或者,实现这个目标的正确方法是什么?
我缺少什么?

解决方案

两种可能的方法:


  1. 您可以创建字典,其值为 Encodable 封装类型,它简单地对基础值进行编码:

      struct EncodableValue:Encodable {
    let value:可编码

    func编码(到编码器:编码器)throws {
    try value.encode(to:encoder)
    }
    }

    然后你可以这样做:

      let dictionary = [
    foo:EncodableValue(value:Foo(string: )),
    bar:EncodableValue(value:Bar(value:42)),
    baz:EncodableValue(value:qux)
    ]

    让data = try! JSONEncoder()。encode(dictionary)


  2. 你可以定义你自己的 Codable 类型,而不是使用字典:

      struct RequestObject:Encodable {
    let foo :Foo
    让bar:Bar
    让baz:String
    }

    let requestObject = RequestObject(
    foo:Foo(string:Hello,world !),
    bar:Bar(value:42),
    baz:qux


    let data = try! JSONEncoder()。encode(requestObject)


这些都假定 Foo Bar 符合 Encodable


I'm looking to store models objects in a Dictionary and would like to serialize the whole dictionary using JSONEncoder into data and subsequently into a string and save it.

The idea is to use Swift 4's out of the box Encodable to ensure anything that I add to the dictionary will be serialized which can include primitives and custom objects (which will themselves conform to Encodable).

The Challenge is what type should I declare the dictionary to be:

  • If I use [String: Any], it won't know how to encode Any, and if I have to cast it into an actual concrete type, it kind of defeats the purpose of generics
  • If I use [String: Encodable], it will crash at run time saying Encodable doesn't conform to itself, which is understandable as it needs a concrete type

In order to tackle this, I thought of creating a wrapper: i.e A protocol with an associated type or a struct with generic type value:

struct Serializable<T: Encodable> {
    var value: T?

    init(value: T) {
       self.value = value
    }
}

But the problem remains, while declaring the type of the aforementioned dictionary, I still have to supply the concrete type..

var dictionary: [String: Serializable<X>]

What should 'X' be here, Or, what's the correct way to achieve this? What am I missing?

解决方案

Two possible approaches:

  1. You can create dictionary whose values are Encodable wrapper type that simply encodes the underlying value:

    struct EncodableValue: Encodable {
        let value: Encodable
    
        func encode(to encoder: Encoder) throws {
            try value.encode(to: encoder)
        }
    }
    

    Then you can do:

    let dictionary = [
        "foo": EncodableValue(value: Foo(string: "Hello, world!")),
        "bar": EncodableValue(value: Bar(value: 42)),
        "baz": EncodableValue(value: "qux")
    ]
    
    let data = try! JSONEncoder().encode(dictionary)
    

  2. You can define your own Codable type instead of using dictionary:

    struct RequestObject: Encodable {
        let foo: Foo
        let bar: Bar
        let baz: String
    }
    
    let requestObject = RequestObject(
        foo: Foo(string: "Hello, world!"), 
        bar: Bar(value: 42),
        baz: "qux"
    )
    
    let data = try! JSONEncoder().encode(requestObject)
    

Needless to say, these both assume that both Foo and Bar conform to Encodable.

这篇关于将编码存储在Swift Dictionary中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆