gpt4 book ai didi

json - 解析真的很复杂的json? swift

转载 作者:可可西里 更新时间:2023-11-01 01:56:55 26 4
gpt4 key购买 nike

我正在尝试解析这个 json:

{
"objName": "Stage",
"sounds": [{
"soundName": "pop",
"soundID": 0,
"md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav",
"sampleCount": 258,
"rate": 11025,
"format": ""
}],
"costumes": [{
"costumeName": "backdrop1",
"baseLayerID": 6,
"baseLayerMD5": "b61b1077b0ea1931abee9dbbfa7903ff.png",
"bitmapResolution": 2,
"rotationCenterX": 480,
"rotationCenterY": 360
}],
"currentCostumeIndex": 0,
"penLayerMD5": "5c81a336fab8be57adc039a8a2b33ca9.png",
"penLayerID": 0,
"tempoBPM": 60,
"videoAlpha": 0.5,
"children": [{
"objName": "img",
"scripts": [[5, 5, [["whenGreenFlag"], ["setSizeTo:", 101], ["gotoX:y:", 0, 0]]]],
"sounds": [{
"soundName": "pop",
"soundID": 0,
"md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav",
"sampleCount": 258,
"rate": 11025,
"format": ""
}],
"costumes": [{
"costumeName": "dotstickie3",
"baseLayerID": 1,
"baseLayerMD5": "bcea2c64c030a2d1ebd7be5ced828583.png",
"bitmapResolution": 2,
"rotationCenterX": 480,
"rotationCenterY": 360
}],
"currentCostumeIndex": 0,
"scratchX": 0,
"scratchY": 0,
"scale": 1.01,
"direction": 90,
"rotationStyle": "normal",
"isDraggable": false,
"indexInLibrary": 1,
"visible": true,
"spriteInfo": {
}
},
{
"objName": "drag",
"scripts": [[5,
5,
[["whenGreenFlag"], ["setSizeTo:", 101], ["gotoX:y:", -413, -7], ["comeToFront"]]],
[10,
129,
[["whenIReceive", "slide"],
["doRepeat",
23,
[["gotoX:y:",
["+", ["xpos"], ["\/", ["-", 40, ["xpos"]], 7]],
-7]]]]]],
"sounds": [{
"soundName": "pop",
"soundID": 0,
"md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav",
"sampleCount": 258,
"rate": 11025,
"format": ""
}],
"costumes": [{
"costumeName": "dotstickie3",
"baseLayerID": 2,
"baseLayerMD5": "e822121ae459cc14df1a5609abe4fd39.svg",
"bitmapResolution": 1,
"rotationCenterX": 296,
"rotationCenterY": 189
}],
"currentCostumeIndex": 0,
"scratchX": 26.928601934244593,
"scratchY": -7,
"scale": 1.01,
"direction": 90,
"rotationStyle": "normal",
"isDraggable": false,
"indexInLibrary": 2,
"visible": true,
"spriteInfo": {
}
},
{
"objName": "clicktostart",
"scripts": [[5,
7,
[["whenGreenFlag"],
["hide"],
["wait:elapsed:from:", 1],
["comeToFront"],
["setGraphicEffect:to:", "ghost", 100],
["show"],
["doRepeat", 25, [["changeGraphicEffect:by:", "ghost", -4]]],
["doWaitUntil", ["mousePressed"]],
["doRepeat", 25, [["changeGraphicEffect:by:", "ghost", 4]]],
["hide"],
["broadcast:", "slide"]]]],
"sounds": [{
"soundName": "pop",
"soundID": 0,
"md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav",
"sampleCount": 258,
"rate": 11025,
"format": ""
}],
"costumes": [{
"costumeName": "costume1",
"baseLayerID": 3,
"baseLayerMD5": "826c7f77077cfba8abddeae0229caf22.svg",
"bitmapResolution": 1,
"rotationCenterX": 139,
"rotationCenterY": -60
},
{
"costumeName": "costume2",
"baseLayerID": 4,
"baseLayerMD5": "a1c639c03c30e32b5baf48ea18621bc4.png",
"bitmapResolution": 2,
"rotationCenterX": 278,
"rotationCenterY": -132
}],
"currentCostumeIndex": 1,
"scratchX": 69,
"scratchY": -30,
"scale": 1,
"direction": 90,
"rotationStyle": "normal",
"isDraggable": false,
"indexInLibrary": 3,
"visible": false,
"spriteInfo": {
}
},
{
"objName": "Sprite1",
"sounds": [{
"soundName": "pop",
"soundID": 0,
"md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav",
"sampleCount": 258,
"rate": 11025,
"format": ""
}],
"costumes": [{
"costumeName": "costume1",
"baseLayerID": 5,
"baseLayerMD5": "7e82b18194f5cc47fba05a7ee5420172.svg",
"bitmapResolution": 1,
"rotationCenterX": 113,
"rotationCenterY": 86
}],
"currentCostumeIndex": 0,
"scratchX": -35,
"scratchY": 21,
"scale": 1,
"direction": 90,
"rotationStyle": "normal",
"isDraggable": false,
"indexInLibrary": 4,
"visible": true,
"spriteInfo": {
}
}],
"info": {
"spriteCount": 4,
"userAgent": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/67.0.3396.99 Safari\/537.36",
"scriptCount": 4,
"projectID": "239379933",
"hasCloudData": true,
"swfVersion": "v461",
"videoOn": false,
"flashVersion": "MAC 30,0,0,154"
}

我查找了如何解析复杂的 json,大多数答案告诉我创建一个 struct 并尝试尽可能匹配数据,所以我创建了这个:

fileprivate struct Stage: Decodable {
struct Sound: Decodable {
var soundName: String;
var soundID: Int;
var md5: String;
var sampleCount: Int;
var rate: Int;
var format: String;
}

struct Costume: Decodable {
var costumeName: String;
var baseLayerID: Int;
var baseLayerMD5: String;
var bitmapResolution: Int;
var rotationCenterX: Int;
var rotationCenterY: Int;
}

struct Child: Decodable {
var objName: String;
var scripts: [[Any]];
var sounds: [Sound];
var costumes: [Costume];
var currentCostumeIndex: Int;
var scratchX: Int;
var scratchY: Int;
var scale: Float;
var direction: Int;
var rotationStyle: String;
var isDraggable: Bool;
var indexInLibrary: Int;
var visible: Bool;
var spriteInfo: SpriteInfo;
}
struct SpriteInfo: Decodable {

}
struct Info: Decodable {
var spriteCount: Int;
var userAgent: String;
var scriptCount: Int;
var projectID: String;
var hasCloudData: Bool;
var swfVersion: String;
var videoOn: Bool;
var flashVersion: String;
}

var objName: String;
var sounds: [Sound];
var costumes: [Costume];
var currentCostumeIndex: Int;
var penLayerMD5: String;
var penLayerID: Int;
var tempoBPM: Int;
var videoAlpha: Float;
var children: [Child];
var info: Info;

当我编译我的 swift 时,它说“错误:类型‘Stage.Child’不符合协议(protocol)‘Decodable’”

我不知道该如何解决这个问题。

如有任何帮助,我们将不胜感激。

最佳答案

简单的部分

像其他人所说的那样,问题在于如何解码 scripts 属性。 JSON 的其余部分非常传统,所以我将它们粘贴到 quicktype.io 并获得以下结构:

struct Stage: Decodable {
let objName: String
let sounds: [Sound]
let costumes: [Costume]
let currentCostumeIndex: Int
let penLayerMD5: String
let penLayerID, tempoBPM: Int
let videoAlpha: Double
let children: [Child]
let info: Info
}

struct Child: Decodable {
let objName: String
let scripts: [Script]? // We will write a custom decoder for `Script`
let sounds: [Sound]
let costumes: [Costume]
let currentCostumeIndex: Int
let scratchX: Double
let scratchY: Int
let scale: Double
let direction: Int
let rotationStyle: String
let isDraggable: Bool
let indexInLibrary: Int
let visible: Bool
let spriteInfo: SpriteInfo
}

struct Costume: Decodable {
let costumeName: String
let baseLayerID: Int
let baseLayerMD5: String
let bitmapResolution, rotationCenterX, rotationCenterY: Int
}

struct Sound: Decodable {
let soundName: String
let soundID: Int
let md5: String
let sampleCount, rate: Int
let format: String
}

struct SpriteInfo: Decodable { }

struct Info: Decodable {
let spriteCount: Int
let userAgent: String
let scriptCount: Int
let projectID: String
let hasCloudData: Bool
let swfVersion: String
let videoOn: Bool
let flashVersion: String
}

解码脚本

All conformances to CustomDebugStringConvertible in this section are optional. You do not have to include them for the code to work. They are to assist debugging only.

脚本对象

下面的 3 个实例都表示 Script 的有效数组:

// Example 1
[
[5, 5, [["whenGreenFlag"], ["setSizeTo:", 101], ["gotoX:y:", 0, 0]]]
]

// Example 2
[
[5, 7, [["whenGreenFlag"],["hide"],["wait:elapsed:from:",1],["comeToFront"],["setGraphicEffect:to:","ghost",100],["show"],["doRepeat",25,[["changeGraphicEffect:by:","ghost",-4]]],["doWaitUntil",["mousePressed"]],["doRepeat",25,[["changeGraphicEffect:by:","ghost",4]]],["hide"],["broadcast:","slide"]]]
]

// Example 3:
[
[5, 5, [["whenGreenFlag"], ["setSizeTo:", 101], ["gotoX:y:", -413, -7], ["comeToFront"]]],
[10, 129, [["whenIReceive", "slide"], ["doRepeat", 23, [["gotoX:y:", ["+", ["xpos"], ["/", ["-", 40, ["xpos"]], 7]], -7]]]]]
]

从这些示例中,我们可以看到一个 Script 以 2 个数字开头,然后是一个看似命令的数组,因此我们可以像这样解码 Script:

struct Script: Decodable, CustomDebugStringConvertible {
var firstNumber: Int
var secondNumber: Int
var commands: [Command]

init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()

self.firstNumber = try container.decode(Int.self)
self.secondNumber = try container.decode(Int.self)
self.commands = try container.decode([Command].self)
}

var debugDescription: String {
return "Script: \(firstNumber), \(secondNumber), \(commands.debugDescription)"
}
}

命令对象

继续命令,一些例子是:

["whenGreenFlag"]
["setSizeTo:", 101]
["whenIReceive", "slide"]
["gotoX:y:", 0, 0]
["doRepeat",25,[["changeGraphicEffect:by:","ghost",4]]]

因此每个 Command 都以一个字符串开头,后跟 0 个或多个参数。每个 Argument 可以是整数、字符串或另一个 Command:

struct Command: Decodable, CustomDebugStringConvertible {
var name: String
var arguments = [CommandArgument]()

init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()

self.name = try container.decode(String.self)
while !container.isAtEnd {
let argument = try container.decode(CommandArgument.self)
self.arguments.append(argument)
}
}

var debugDescription: String {
return "(\(name) \(arguments.debugDescription))"
}
}

CommandArgument 对象

CommandArgument 示例:

101
"slide"
["doRepeat", 23, [["gotoX:y:", ["+", ["xpos"], ["/", ["-", 40, ["xpos"]], 7]], -7]]]

每个 CommandArgument 可以是整数、字符串或其他命令。我们将使用具有关联值的枚举来表示它:

enum CommandArgument: Decodable, CustomDebugStringConvertible {
case integer(value: Int)
case string(value: String)
case command(value: Command)

init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()

if let intValue = try? container.decode(Int.self) {
self = .integer(value: intValue)
} else if let stringValue = try? container.decode(String.self) {
self = .string(value: stringValue)
} else if let commandValue = try? container.decode(Command.self) {
self = .command(value: commandValue)
} else if let commandArray = try? container.decode([Command].self) {
self = .command(value: commandArray.first!)
} else {
throw NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [NSLocalizedDescriptionKey: "Unrecognized argument type"])
}
}

var debugDescription: String {
switch self {
case .integer(let intValue):
return "\(intValue)"
case .string(let stringValue):
return stringValue
case .command(let commandValue):
return commandValue.debugDescription
}
}
}

最后

现在您已经编写了所有内容,下面是解码整个 JSON 的方法:

let stage = try JSONDecoder().decode(Stage.self, from: json)

关于json - 解析真的很复杂的json? swift ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51921713/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com