https://app.quicktype.io, правильный JSON
{ "layers":[
{
"name":"img",
"elements":[
{
"elementData":{
"imageId":"32dd800000002"
},
"transform":{
"xScale":100,
"yScale":100
},
"active":true
},
{
"component":{
"glyphName":"e",
"layerName":"img"
}
},
{
"elementData":{
"composite":{
"builder":{
"builderGroup":{
}
}
}
},
"transform":{
"xOffset":120
},
"nonSpacing":true
}
],
"color":"maroon",
"active":true
},
{
"name":"Black",
"elements":[
{
"component":{
"glyphName":"e",
"layerName":"Black"
}
},
{
"elementData":{
"name":"caron",
"contours":[
{
"nodes":[
"80 577",
"107 549 142 550 167 575 s"
]
}
]
}
}
],
"color":"#00802a"
},
{
"name":"Thin",
"elements":[
{
"component":{
"glyphName":"e",
"layerName":"Thin"
}
},
{
"elementData":{
"name":"caron",
"contours":[
{
"nodes":[
"102 597 s",
"118 580 132 580 148 597 s",
"250 710",
"235 726",
"110 613",
"140 613",
"14 726",
"-1 710"
]
}
]
}
}
],
"color":"#6a8000"
}
]}
Анализировать
struct Welcome: Codable {
let layers: [Layer]
}
struct Layer: Codable {
let name: String
let elements: [Element]
let color: String
let active: Bool?
}
struct Element: Codable {
let elementData: ElementData?
let transform: Transform?
let active: Bool?
let component: Component?
let nonSpacing: Bool?
}
struct Component: Codable {
let glyphName, layerName: String
}
struct ElementData: Codable {
let imageID: String?
let composite: Composite?
let name: String?
let contours: [Contour]?
enum CodingKeys: String, CodingKey {
case imageID = "imageId"
case composite, name, contours
}
}
struct Composite: Codable {
let builder: Builder
}
struct Builder: Codable {
let builderGroup: BuilderGroup
}
struct BuilderGroup: Codable {
}
struct Contour: Codable {
let nodes: [String]
}
struct Transform: Codable {
let xScale, yScale, xOffset: Int?
}
do {
let res = try JSONDecoder().decode(Welcome.self,from:data)
}
catch {
print(error)
}
Изменить:
struct Welcome: Codable {
let layers: [Layer]
}
struct Layer: Codable {
let name: String
let elements: [Element]
let color: String
let active: Bool?
}
struct Element: Codable {
let elementData: ElementDataUnion?
let transform: Transform?
let active: Bool?
let component: Component?
let nonSpacing: Bool?
}
struct Component: Codable {
let glyphName, layerName: String
}
enum ElementDataUnion: Codable {
case elementDataClass(ElementDataClass)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
if let x = try? container.decode(ElementDataClass.self) {
self = .elementDataClass(x)
return
}
throw DecodingError.typeMismatch(ElementDataUnion.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ElementDataUnion"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .elementDataClass(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
struct ElementDataClass: Codable {
let composite: Composite?
let name: String?
let contours: [Contour]?
}
struct Composite: Codable {
let builder: Builder
}
struct Builder: Codable {
let builderGroup: BuilderGroup
}
struct BuilderGroup: Codable {
}
struct Contour: Codable {
let nodes: [String]
}
struct Transform: Codable {
let xScale, yScale, xOffset: Int?
}
Если вам нужно, чтобы elementData
был словарём / строкой ,,,,, elements
был массивом / строкой, тогда используйте
struct Welcome: Codable {
let layers: [Layer]
}
struct Layer: Codable {
let name: String
let elements: Elements
let color: String
let active: Bool?
}
enum Elements: Codable {
case elementArray([Element])
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode([Element].self) {
self = .elementArray(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(Elements.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Elements"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .elementArray(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
struct Element: Codable {
let component: Component?
let elementData: ElementDataUnion?
}
struct Component: Codable {
let glyphName, layerName: String
}
enum ElementDataUnion: Codable {
case elementDataClass(ElementDataClass)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
if let x = try? container.decode(ElementDataClass.self) {
self = .elementDataClass(x)
return
}
throw DecodingError.typeMismatch(ElementDataUnion.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ElementDataUnion"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .elementDataClass(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
struct ElementDataClass: Codable {
let name: String
let contours: [Contour]
}
struct Contour: Codable {
let nodes: [String]
}