- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试解析这个 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/
有没有办法在 .swift 文件(编译成 .swift 模块)中声明函数,如下所示: 你好.swift func hello_world() { println("hello world")
我正在尝试使用 xmpp_messenger_ios 和 XMPPFramework 在 iOS 上执行 MUC 这是加入房间的代码。 func createOrJoinRoomOnXMPP()
我想在我的应用程序上创建一个 3D Touch 快捷方式,我已经完成了有关快捷方式本身的所有操作,它显示正确,带有文本和图标。 当我运行这个快捷方式时,我的应用程序崩溃了,因为 AppDelegate
我的代码如下: let assetTag = Expression("asset_tag") let query2 = mdm.select(mdm[assetTag],os, mac, lastRe
我的 swift 代码如下所示 Family.arrayTuple:[(String,String)]? = [] Family.arrayTupleStorage:String? Family.ar
这是我的 JSON,当我读取 ord 和 uniq 数据时出现错误 let response2 : [String: Any] = ["Response":["status":"SUCCESS","
我想将 swift 扩展文件移动到 swift 包中。但是,将文件移动到 swift 包后,我遇到了这种错误: "Type 'NSAttributedString' has no member 'ma
使用CocoaPods,我们可以设置以下配置: pod 'SourceModel', :configurations => ['Debug'] 有什么方法可以用 Swift Package Manag
我正在 Xcode 中开发一个 swift 项目。我将其称为主要项目。我大部分都在工作。我在日期选择器、日期范围和日期数学方面遇到了麻烦,因此我开始了另一个名为 StarEndDate 的项目,其中只
这是 ObjectiveC 代码: CCSprite *progress = [CCSprite spriteWithImageNamed:@"progress.png"]; mProgressBar
我正在创建一个命令行工具,在 Xcode 中使用 Swift。我想使用一个类似于 grunt 的配置文件确实如此,但我希望它是像 Swift 包管理器的 package.swift 文件那样的快速代码
我假设这意味着使用系统上安装的任何 swift 运行脚本:#!/usr/bin/swift 如何指定脚本适用的解释器版本? 最佳答案 Cato可用于此: #!/usr/bin/env cato 1.2
代码说完全没问题,没有错误,但是当我去运行模拟器的时候,会出现这样的字样: (Swift.LazyMapCollection (_base:[ ] 我正在尝试创建一个显示报价的报价应用。 这是导入
是否可以在运行 Swift(例如 Perfect、Vapor、Kitura 等)的服务器上使用 RealmSwift 并使用它来存储数据? (我正在考虑尝试将其作为另一种解决方案的替代方案,例如 no
我刚开始学习编程,正在尝试完成 Swift 编程书中的实验。 它要求““编写一个函数,通过比较两个 Rank 值的原始值来比较它们。” enum Rank: Int { case Ace = 1 ca
在您将此问题标记为重复之前,我检查了 this question 它对我不起作用。 如何修复这个错误: error: SWIFT_VERSION '5.0' is unsupported, suppo
从 Xcode 9.3 开始,我在我的模型中使用“Swift.ImplicitlyUnwrappedOptional.some”包裹了我的字符串变量 我不知道这是怎么发生的,但它毁了我的应用程序! 我
这个问题在这里已经有了答案: How to include .swift file from other .swift file in an immediate mode? (2 个答案) 关闭 6
我正在使用 Swift Package Manager 创建一个应用程序,我需要知道构建项目的配置,即 Debug 或 Release。我试图避免使用 .xcodeproj 文件。请有人让我知道这是否
有一个带有函数定义的文件bar.swift: func bar() { println("bar") } 以及一个以立即模式运行的脚本foo.swift: #!/usr/bin/xcrun s
我是一名优秀的程序员,十分优秀!