0

正如问题所述:我有一个符合新Encodable协议的结构,并希望在结构本身中插入不作为变量或常量存在的键和值。我当前的解决方法是将它们作为常量添加到结构中,其唯一目的是添加到生成的 JSON 输出中。有没有办法做到这一点func encode(to encoder: Encoder) throws { ... }


背景资料

我有一个相当大的 Swift 4 项目,它需要一个 JSON 输出来在项目本身之外生成统计信息和可视化,所以我几乎所有的结构、类和枚举都符合新Encodable协议。输出已经在工作,但在某些方面可读性很差。特别是在一个描述光栅化工厂布局中的字段的结构中:

该字段具有包含以下情况的自定义位置(带有坐标x: Inty: Int)和自定义内容:enum FieldType

case wall
case entrance(robots: Set<Robot>)
case exit(robots: Set<Robot>)
case workstation(object: Workstation)
case robot(object: Robot)
case empty

Position, FieldType, Robot,WorkstationField本身已经实现Encodable,但问题是我的字段的 JSON 输出如下所示:

...
{
    "content" : "empty",
    "position" : {
        "x" : 9,
        "y" : 6
    }
},
{
    "content" : "empty",
    "position" : {
        "x" : 10,
        "y" : 6
    }
},
{
    "content" : {
        "id" : 3,
        "state" : "idle",
        "type" : "C",
        "position" : {
            "x" : 11,
            "y" : 6
        }
    },
    "position" : {
        "x" : 11,
        "y" : 6
    }
},
{
    "content" : "empty",
    "position" : {
        "x" : 12,
        "y" : 6
    }
},
...

正如您所看到的,在位置 (11, 6) 处除了空白字段之外还有其他内容,但不知道在我的模拟中只有工作站处于空闲状态,因此无法知道该字段包含什么内容。所以我尝试通过将 CodingKeys 定义为枚举来向我的工作站模型(机器人模型中的类比)添加一个"object"带有值的键:"workstation""robot"

private enum CodingKeys: String, CodingKey {
    case object
    case id
    case state
    case type
    case position
}

这导致我struct Workstation不再符合Encodable. 所以我找到的唯一解决方案是添加一个常量let object = "workstation",但这是一个常量,其唯一目的是添加到输出中,我想避免这种情况。

4

1 回答 1

1

您必须为以下内容编写自定义编码器FieldType

enum FieldType: Encodable {
    case wall
    case entrance(robots: Set<Robot>)
    case exit(robots: Set<Robot>)
    case workstation(object: Workstation)
    case robot(object: Robot)
    case empty

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()

        switch self {
        case .wall:
            try container.encode("wall")
        case .entrance(let robotset):
            try container.encode(robotset)
        case .exit(let robotSet):
            try container.encode(robotSet)
        case .workstation(let workstation):
            try container.encode(workstation)
        case .robot(let robot):
            try container.encode(robot)
        case .empty:
            try container.encode("empty")
        }
    }
}

(这假设Robot并且Workstation已经Encodable

于 2017-09-03T19:27:20.433 回答