首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >格式错误的JSON条目有时是数组,有时是字典

格式错误的JSON条目有时是数组,有时是字典
EN

Stack Overflow用户
提问于 2022-01-04 07:29:20
回答 1查看 121关注 0票数 0

我正在尝试解析curl "https://blockchain.info/block-height/699999"的结果

在其结果中,它将spending_outpoints作为字典数组返回,但有时它使用的不是数组"spending_outpoints" = [ ... ],而是使用空字典"spending_outpoints" = { }。我已经实现了一个解决方案,但是这个错误也失败了:

代码语言:javascript
运行
AI代码解释
复制
AppVisualizer/AppVisualizerApp.swift:71: Fatal error: 'try!' 
expression unexpectedly raised an error: 
Swift.DecodingError.typeMismatch(Swift.Dictionary<Swift.String, Any>, 
Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: 
"blocks", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 
0), CodingKeys(stringValue: "tx", intValue: nil), 
_JSONKey(stringValue: "Index 0", intValue: 0), 
CodingKeys(stringValue: "inputs", intValue: nil), 
_JSONKey(stringValue: "Index 0", intValue: 0), 
CodingKeys(stringValue: "prev_out", intValue: nil), 
CodingKeys(stringValue: "spending_outpoints", intValue: nil)], 
debugDescription: "Expected to decode Dictionary<String, Any> but 
found an array instead.", underlyingError: nil))

解决方法是枚举SpendingOutpoints,它要么是数组,要么是字典。因为字典应该是空的,所以值类型应该是无关的。

我的相关可编码结构是:

代码语言:javascript
运行
AI代码解释
复制
        struct SpendingOutpoint : Codable {
            var tx_index            : UInt64
            var n                   : UInt32
        }
        enum SpendingOutpoints : Codable {
            case array(Array<SpendingOutpoint>)
            case dictionary(Dictionary<String,String>)
            init(from decoder: Decoder) throws {
                let container = try decoder.container(keyedBy: CodingKeys.self)
                if let array = try? container.decode(Array<SpendingOutpoint>.self, forKey: .array) {
                    self = .array(array)
                    return
                }
                if let dictionary = try? container.decode(Dictionary<String,String>.self, forKey: .dictionary) {
                    self = .dictionary(dictionary)
                    return
                }
                throw DecodingError.typeMismatch(SpendingOutpoints.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unexptected type: expecting array or dictionary"))
            }
        }
        struct Output : Codable {
            var type                : Int
            var spent               : Bool
            var script              : String
            var value               : UInt64
            var spending_outpoints  : SpendingOutpoints
            var tx_index            : UInt64
            var n                   : UInt64
            var addr                : String?
        }
代码语言:javascript
运行
AI代码解释
复制
let url = Bundle.main.url(forResource: "blockheight", withExtension: "json")!
let data1 = try! JSONDecoder().decode(API.Blockchain.Blockheight.self, from: Data.init(contentsOf: url))

完整的Codable结构集:

代码语言:javascript
运行
AI代码解释
复制
struct API {
    struct Blockchain {
        enum SpendingOutpoints : Codable {
            case array(Array<SpendingOutpoint>)
            case dictionary(Dictionary<String,String>)
            init(from decoder: Decoder) throws {
                let container = try decoder.container(keyedBy: CodingKeys.self)
                if let array = try? container.decode(Array<SpendingOutpoint>.self, forKey: .array) {
                    self = .array(array)
                    return
                }
                if let dictionary = try? container.decode(Dictionary<String,String>.self, forKey: .dictionary) {
                    self = .dictionary(dictionary)
                    return
                }
                throw DecodingError.typeMismatch(SpendingOutpoints.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unexptected type: expecting array or dictionary"))
            }
        }
        struct SpendingOutpoint : Codable {
                //            {
                //            "tx_index":5602502841772452,
                //            "n":0
                //            }
            var tx_index            : UInt64
            var n                   : UInt32
        }
        struct Output : Codable {
                //            "type":0,
                //            "spent":true,
                //            "value":626178339,
                //            "spending_outpoints":[
                //                {
                //                    "tx_index":4405887896017968,
                //                    "n":2
                //                }
                //            ],
                //            "n":0,
                //            "tx_index":4989293645553533,
                //            "script":"76a91474e878616bd5e5236ecb22667627eeecbff54b9f88ac",
                //            "addr":"1Bf9sZvBHPFGVPX71WX2njhd1NXKv5y7v5"
            var type                : Int
            var spent               : Bool
            var script              : String
            var value               : UInt64
            var spending_outpoints  : SpendingOutpoints
            var tx_index            : UInt64
            var n                   : UInt64
            var addr                : String?
        }
        struct Input : Codable {
                //            "sequence":4294967295,
                //            "witness":"01200000000000000000000000000000000000000000000000000000000000000000",
                //            "script":"03c9f00a1362696e616e63652f3831305000fb0162c56408fabe6d6d85e315917dcf79bdee12fcf0b412ca00bdbe3ec986dec2a30884d4b5ff512d1a0200000000000000a4aa0000ec190200",
                //            "index":0,
                //            "prev_out":{
            var sequence            : UInt64
            var witness             : String
            var script              : String
            var index               : UInt32
            var prev_out            : Output
        }
        struct Tx : Codable {
                //            "hash":"f2b8c6f1586e238d9f56e16fdfe8d31e5c086be5889cb7dbcf244de5bd923b9f",
                //            "ver":1,
                //            "vin_sz":1,
                //            "vout_sz":4,
                //            "size":343,
                //            "weight":1264,
                //            "fee":0,
                //            "relayed_by":"0.0.0.0",
                //            "lock_time":0,
                //            "tx_index":5602502841772452,
                //            "double_spend":false,
                //            "time":1641209474,
                //            "block_index":717001,
                //            "block_height":717001,
                //            "inputs":[
            var hash            : String
            var ver             : Int
            var vin_sz          : Int
            var vout_sz         : Int
            var size            : Int
            var weight          : Int
            var fee             : Double
            var relayed_by      : String
            var lock_time       : UInt32
            var tx_index        : UInt64
            var double_spend    : Bool
            var time            : UInt32
            var block_index     : UInt32
            var block_height    : UInt32
            var inputs          : [Input]
            var out             : [Output]
        }
        struct Block : Codable {
                //            "hash":"00000000000000000003d03aab20439e69f319e847f101ccd8a7cfbef9473561",
                //            "ver":545259520,
                //            "prev_block":"00000000000000000009396fbe5531a11f90bae421aa1621def645e0fe5e4e1b",
                //            "mrkl_root":"f2b8c6f1586e238d9f56e16fdfe8d31e5c086be5889cb7dbcf244de5bd923b9f",
                //            "time":1641209474,
                //            "bits":386635947,
                //            "next_block":[
                //            "0000000000000000000b6713adeb66d64cacefbcc5b402db608f75d6edd0f2cf"
                //            ],
                //            "fee":0,
                //            "nonce":3212120200,
                //            "n_tx":1,
                //            "size":424,
                //            "block_index":717001,
                //            "main_chain":true,
                //            "height":717001,
                //            "weight":1588,
                //            "tx":[
            
            var hash        : String
            var ver         : UInt64
            var prev_block  : String
            var mrkl_root   : String
            var time        : UInt64
            var bits        : UInt64
            var next_block  : [String]
            var fee         : UInt64
            var nonce       : UInt32
            var n_tx        : Int
            var size        : Int
            var block_index : UInt
            var main_chain  : Bool
            var height      : UInt32
            var weight      : UInt32
            var tx          : [Tx]
        }
        struct Blockheight : Codable {
            var blocks : [Block]
        }
    }
}

以下是json文件:

代码语言:javascript
运行
AI代码解释
复制
{
    "blocks":[
        {
            "hash":"0000000000000000000aa3ce000eb559f4143be419108134e0ce71042fc636eb",
            "ver":832872452,
            "prev_block":"00000000000000000007a60f43d15d097bd369dd8c6c53f12b32f649f979e85e",
            "mrkl_root":"a961ea5c3420ca74d28e33e7dfe5e871da6db36ee63d62687e791a9f3098596d",
            "time":1631332753,
            "bits":386877668,
            "next_block":[
                "0000000000000000000590fc0f3eba193a278534220b2b37e9849e1a770ca959"
            ],
            "fee":1178339,
            "nonce":648207636,
            "n_tx":292,
            "size":141595,
            "block_index":699999,
            "main_chain":true,
            "height":699999,
            "weight":372724,
            "tx":[
                {
                    "hash":"3a7e5833d940a75fc542364d4eba8e3ea37b84f4c061b35c3ceafb629be3cd8d",
                    "ver":2,
                    "vin_sz":1,
                    "vout_sz":3,
                    "size":293,
                    "weight":1064,
                    "fee":0,
                    "relayed_by":"0.0.0.0",
                    "lock_time":0,
                    "tx_index":4989293645553533,
                    "double_spend":false,
                    "time":1631332753,
                    "block_index":699999,
                    "block_height":699999,
                    "inputs":[
                        {
                            "sequence":4294967295,
                            "witness":"01200000000000000000000000000000000000000000000000000000000000000000",
                            "script":"035fae0a0413789b644254432e636f6d2f7563386575fabe6d6da8a2adde9c18f88da1fd1c3c529ce4165f9e4b2f87164bcb9f1a7a07b0c89dce020000008e9b20aa2058499a0000000000000000",
                            "index":0,
                            "prev_out":{
                                "spent":true,
                                "script":"",
                                "spending_outpoints":[
                                    {
                                        "tx_index":4989293645553533,
                                        "n":0
                                    }
                                ],
                                "tx_index":0,
                                "value":0,
                                "n":4294967295,
                                "type":0
                            }
                        }
                    ],
                    "out":[
                        {
                            "type":0,
                            "spent":true,
                            "value":626178339,
                            "spending_outpoints":[
                                {
                                    "tx_index":4405887896017968,
                                    "n":2
                                }
                            ],
                            "n":0,
                            "tx_index":4989293645553533,
                            "script":"76a91474e878616bd5e5236ecb22667627eeecbff54b9f88ac",
                            "addr":"1Bf9sZvBHPFGVPX71WX2njhd1NXKv5y7v5"
                        },
                        {
                            "type":0,
                            "spent":false,
                            "value":0,
                            "spending_outpoints":{
                            },
                            "n":1,
                            "tx_index":4989293645553533,
                            "script":"6a24aa21a9ed2f5cb87274312f2e7f785e34be6db44afec9d1263eb0977b6e3c8c7f7df6ec7d"
                        },
                        {
                            "type":0,
                            "spent":false,
                            "value":0,
                            "spending_outpoints":{
                            },
                            "n":2,
                            "tx_index":4989293645553533,
                            "script":"6a24b9e11b6de2202207ad664f985557d8de23adafd23c36fc708614dd2220b58e735dfd0ca9"
                        }
                    ]
                }
            ]
        }
    ]
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-04 07:52:07

这是一个可行的解决方案。为了演示,只需从示例JSON中删除除spending_outpoints和周围数据结构之外的所有数据即可。

代码语言:javascript
运行
AI代码解释
复制
let json = """
[
    {
        "spending_outpoints": [{
            "tx_index": 4405887896017968,
            "n": 2
        }]
    },
    {
        "spending_outpoints": {}
    },
    {
        "spending_outpoints": {}
    }
]
"""

当我们得到字典数组时,下面是字典的一个结构:

代码语言:javascript
运行
AI代码解释
复制
struct Outpoint: Decodable {
    let tx_index: Int
    let n: Int
}

下面是接受数组或(空)字典的union:

代码语言:javascript
运行
AI代码解释
复制
enum ArrayOrDict: Decodable {
    case array(Array<Outpoint>)
    case dict(Dictionary<String,String>)
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let array = try? container.decode(Array<Outpoint>.self) {
            self = .array(array)
            return
        }
        if let dict = try? container.decode(Dictionary<String,String>.self) {
            self = .dict(dict)
            return
        }
        throw DecodingError.typeMismatch(ArrayOrDict.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Default"))
    }
}

以下是整个字典类型:

代码语言:javascript
运行
AI代码解释
复制
struct Outer: Decodable {
    let spendingOutpoints: ArrayOrDict
    enum CodingKeys: String, CodingKey {
        case spendingOutpoints = "spending_outpoints"
    }
}

好了,我们开始:

代码语言:javascript
运行
AI代码解释
复制
let jsonData = json.data(using: .utf8)!
do {
    let result = try JSONDecoder().decode([Outer].self, from: jsonData)
} catch {
    print(error)
}

这没有任何错误。因此,您应该能够构建回您的实际数据结构。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70581212

复制
相关文章
java数组如何赋值_java数组如何赋值
Java 语言中数组必须先初始化,然后才可以使用。所谓初始化,就是为数组的数组元素分配内存空间,并为每个数组元素赋初始值。
全栈程序员站长
2022/09/13
4.1K0
java数组如何赋值_java数组如何赋值
如何给结构体内声明的二维数组赋值
最近在用C++做一个象棋小游戏,为了规避全局变量的使用,想使用结构体来声明需要使用的数据。给其中用来存储棋盘信息的二维数组赋值时却遇到了问题:
英雄爱吃土豆片
2020/10/29
2.6K0
Java基础:数组的声明,循环,赋值,拷贝。
下面,语句就是声明了一个可以存储100个整数的数组。可以根据你的实际需求,更换int类型为你需要的数据类型。
呆呆
2021/10/04
1.1K0
Mysql 声明变量并赋值
注意上面两种赋值符号,使用set时可以用“=”或“:=”,但是使用select时必须用“:=赋值”
一个会写诗的程序员
2018/08/17
4.1K0
MySQL变量声明、赋值和使用
上面两种赋值符号,使用set时可以用“=”或“:=”,但是使用select时必须用“:=赋值”
Java那些事儿
2020/07/21
3.5K0
java对象组声明_如何在Java中声明对象数组?
可以创建对象类数组,该数组可以接受任何类型的对象。在此类数组上运行期间,可以使用instanceof运算符。
全栈程序员站长
2022/08/30
3.9K0
Java中如何声明数组「建议收藏」
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/137070.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/05
1.8K0
Java数组赋值
String [] word = {"hello", "world", "java"}; String [] dest = new String[3]; dest = words; words[0] = "nihao"; for(String t: dest){ System.out.println(t); } String [] dest2 = {"12","23","
一灰灰blog
2018/02/06
2.1K0
数组解构赋值
倘若A代表人生的成功,那么公式是:A =X+Y+Z。X是工作,Y是游戏,z是保持缄默。——(美)爱因斯坦 我们以前从一个数组中获取第一项,可能是如下写法: let list = [1,2,3] let i = list[0] 有了解构赋值,可以如下写法: let list = [1,2,3] let [i] = list 如果稍微复杂点,例如下面这样从对象中取出来数组: let ruben = {hobby:['anime']} let favorite = ruben.hobby[0] 就可以写成
阿超
2022/08/17
1.5K0
Java 数组声明
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/137260.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/05
8370
VBA数组(二)声明数组
大家好,上节介绍了数组的维度,索引号、上界和下界的知识,本节继续介绍数组的基础知识,包括数组的分类,以及如何声明数组。关于数组的内容相对抽象,会尽量介绍详尽。
无言之月
2019/10/13
3.5K0
VBA数组(三)数组赋值
大家好,上节介绍了在使用数组之前如何声明数组,本节就来介绍静态数组如何赋值。(动态数组会单独一节讲解)
无言之月
2019/10/13
12.5K0
解构赋值的作用_数组解构赋值
数组解构是非常简单简洁的,在赋值表达式的左侧使用数组字面量,数组字面量中的每个变量名称映射为解构数组的相同索引项
全栈程序员站长
2022/11/03
3.9K0
java如何键盘录入数组_从键盘输入给数组赋值
有时候在编写Jave的时候需要键盘输入一个数组,本小白也是看了几篇博客后才知道了如何在自己的程序中进行键盘输入,废话不多说,直接上代码: 第一种方法:(不限制输入数组的长度)
全栈程序员站长
2022/08/03
3.5K0
java如何键盘录入数组_从键盘输入给数组赋值
Matlab赋值_matlab二维数组赋值
y=[106。42 108。26 109。58 109。5 110 109。93 110。49 110。
全栈程序员站长
2022/11/10
2.2K0
【说站】java数组赋值
在数组的学习方面,我们不光有创建、初始化等操作,赋值也是操作数组必学的知识点。在赋值方面有两种方式,一种是先定义再赋值,另一种是边定义边赋值。
很酷的站长
2022/11/23
1.6K0
【说站】java数组赋值
Java之数组赋值机制
基本数据类型赋值,这个值就是具体的数据,而且相互不影响。 int n1 = 2; int n2 = n1; 数组在默认情况下是引用传递,赋的值是地址。 看一个案例,并分析数组赋值的内存图(重点, 难点. )。 ArrayAssign.java int[] arr1 = {1,2,3}; int[] arr2 = arr1; //基本数据类型赋值, 赋值方式为值拷贝 //n2的变化,不会影响到n1的值 int n1 = 10; int n2 = n1; n2 = 80; System.out
兮动人
2021/06/11
1.4K0
Java之数组赋值机制
Go 专栏|变量和常量的声明与赋值
上篇文章介绍了环境搭建,并完成了学习 Go 的第一个程序 Hello World。这篇文章继续学习 Go 的基础知识,来看看变量,常量的声明与赋值。
AlwaysBeta
2021/09/02
1.1K0
Go 专栏|变量和常量的声明与赋值
数组的声明以及分类
②$arr=array(key1=>value1,key1=>value2,key1=>value3);
十月梦想
2018/08/29
7370
Python-声明数组(列表)
在 Python 中,数组被称为列表(list),定义一个列表需要使用中括号 []
用户9006224
2023/04/22
7290

相似问题

通过javascript播放mp4视频

20

使用jquery播放视频的lightbox效果?

23

在WordPress插件的Lightbox中播放YouTube视频

15

如何在html视频标签中播放mp4视频,视频是通过multer上传的

24

lightbox中的视频有问题吗?

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档