我在解码JSON结构时遇到问题,我无法对其进行更改以使其更易于解码(它来自firebase)。
如何将以下JSON解码为对象?问题是如何转换“ 7E7-M001”。这是带有抽屉的容器的名称。抽屉名称也用作键。
{
"7E7-M001" : {
"Drawer1" : {
"101" : {
"Partnumber" : "F101"
},
"102" : {
"Partnumber" : "F121"
}
}
},
"7E7-M002": {
"Drawer1": {
"201": {
"Partnumber": "F201"
},
"202": {
"Partnumber": "F221"
}
}
}
}
我必须在Container&Drawer类中解决哪些问题,才能将键作为title属性和这些类中的对象数组?
class Container: Codable {
var title: String
var drawers: [Drawer]
}
class Drawer: Codable {
var title: String
var tools: [Tool]
}
class Tool: Codable {
var title: String
var partNumber: String
enum CodingKeys: String, CodingKey {
case partNumber = "Partnumber"
}
}
首先,我将略作简化,以便我可以集中讨论此问题的重点。我将使所有内容不变,用结构替换类,仅实现Decodable。使此可编码成为一个单独的问题。
处理未知值键的中心工具是CodingKey,它可以处理任何字符串:
struct TitleKey: CodingKey {
let stringValue: String
init?(stringValue: String) { self.stringValue = stringValue }
var intValue: Int? { return nil }
init?(intValue: Int) { return nil }
}
第二个重要工具是了解自己的头衔的能力。这意味着询问解码器“我们在哪里?” 那是当前编码路径中的最后一个元素。
extension Decoder {
func currentTitle() throws -> String {
guard let titleKey = codingPath.last as? TitleKey else {
throw DecodingError.dataCorrupted(.init(codingPath: codingPath,
debugDescription: "Not in titled container"))
}
return titleKey.stringValue
}
}
然后,我们需要一种以这种方式对“标题”元素进行解码的方法:
extension Decoder {
func decodeTitledElements<Element: Decodable>(_ type: Element.Type) throws -> [Element] {
let titles = try container(keyedBy: TitleKey.self)
return try titles.allKeys.map { title in
return try titles.decode(Element.self, forKey: title)
}
}
}
这样,我们可以为这些“有标题的”事物发明一个协议并对其进行解码:
protocol TitleDecodable: Decodable {
associatedtype Element: Decodable
init(title: String, elements: [Element])
}
extension TitleDecodable {
init(from decoder: Decoder) throws {
self.init(title: try decoder.currentTitle(),
elements: try decoder.decodeTitledElements(Element.self))
}
}
这就是大部分工作。我们可以使用此协议使高层解码非常容易。只是实施init(title:elements:)
。
struct Drawer: TitleDecodable {
let title: String
let tools: [Tool]
init(title: String, elements: [Tool]) {
self.title = title
self.tools = elements
}
}
struct Container: TitleDecodable {
let title: String
let drawers: [Drawer]
init(title: String, elements: [Drawer]) {
self.title = title
self.drawers = elements
}
}
Tool
有点不同,因为它是叶节点并且还有其他要解码的内容。
struct Tool: Decodable {
let title: String
let partNumber: String
enum CodingKeys: String, CodingKey {
case partNumber = "Partnumber"
}
init(from decoder: Decoder) throws {
self.title = try decoder.currentTitle()
let container = try decoder.container(keyedBy: CodingKeys.self)
self.partNumber = try container.decode(String.self, forKey: .partNumber)
}
}
那只是最高级。我们将创建一个Containers
类型来包装所有内容。
struct Containers: Decodable {
let containers: [Container]
init(from decoder: Decoder) throws {
self.containers = try decoder.decodeTitledElements(Container.self)
}
}
并使用它,解码顶级Containers
:
let containers = try JSONDecoder().decode(Containers.self, from: json)
print(containers.containers)
请注意,由于JSON对象不是按顺序保留的,因此数组可能与JSON的顺序不同,并且两次运行之间的顺序也可能不同。
要旨
我有这个JSON输入,我想通过jolt规范转换它 预期的输出应该是这样的 请问这可以通过 Jolt 实现吗?我已经尝试了几种可能性,但我对 Jolt 很陌生,到目前为止还没有成功
问题内容: 我有一个用于存储优惠券/折扣的表,并且我想将coupon_code列用作主键,即。 我的理由是,每个优惠券都将具有唯一的代码,而我将要运行的唯一命令是 我不会进行任何联接或索引编制,并且我看不到该表中有超过几百个条目。 在我看来,这可以,但是我不知道是否有任何我想念的东西。 问题答案: 从某种意义上说,您当然可以,您的RDBMS将允许您这样做。这个问题的答案,你是否没有问题 应该 做到
我正在为我的应用程序创建一个简单的活动流。 用户执行操作,活动直接存储在MYSQL中的“activities”表中,并返回唯一的“activity_id”。 从数据库中检索该用户的“followers”的数组,并且对于每个followers我将这个新的activity_id推入Redis中的列表。 当用户查看他们的流时,我根据他们的用户ID从redis检索活动ID的数组。然后,我执行一个简单的MY
问题内容: 我正在寻找一种在插入新行时使其hibernate以使用oracle 函数的方法。当前,我的数据库表是默认表,因此,如果hibernate只是生成忽略该值的SQL即可。 我已完成所有工作,但是当前它正在使用system-uuid生成器以代码生成UUID / GUID: 很好,但是我更希望向导是由数据库生成的,因此它们将是顺序的,并可能具有更好的性能。另外,我只想知道如何配置它。 我使用注
问题内容: 我有一个.NET项目。我正在使用JSON.NET库。我需要使用该库来解析一些JSON。我的JSON看起来像这样: 该对象实际上只是键/值对的列表。我试图弄清楚如何使用JSON.NET来1)解析此JSON和2)通过键/值对进行循环。有没有办法做到这一点?如果是这样,怎么办? 我唯一看到的是将反序列化为强类型的对象。 非常感谢! 问题答案: 您可以反序列化为 由于JObject实现,因此您
问题 > 我想要一个键值对列表,比如HashMap,或者其他推荐的。 此列表应包含用于检索值的唯一键对象。 键不应该是字符串,因为字符串不是唯一的,可以传递任何值。 常量也是有限的,也使用字符串的概念,不应该被考虑。 示例 > 在这个阶段,我创建了一个包含所有键的枚举。例如,枚举颜色{RED,BLUE},然后将其添加到新的HashMap中。 因此,检索颜色的唯一方法是将枚举用作键列表[color.