Skip to content

Commit 4a1bcac

Browse files
author
Sven
committed
feat: json 转模 支持多层json 嵌套。
1 parent e394f41 commit 4a1bcac

File tree

4 files changed

+251
-2
lines changed

4 files changed

+251
-2
lines changed

SwiftJSONModeler For Xcode.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
C92A971824E513F900C87CCD /* ErrorCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CB247F241F559C00F4D5CE /* ErrorCenter.swift */; };
1616
C92A971D24E514FB00C87CCD /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C92A971C24E514FB00C87CCD /* Constants.swift */; };
1717
C92A971E24E5150600C87CCD /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C92A971C24E514FB00C87CCD /* Constants.swift */; };
18+
C935B49C24EA24BE00E48231 /* JSONHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C935B49B24EA24BE00E48231 /* JSONHelper.swift */; };
19+
C935B49E24EA56EF00E48231 /* JSONHelperTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C935B49D24EA56EF00E48231 /* JSONHelperTest.swift */; };
1820
C94AFC01241F4AE600389AF3 /* YApiHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C94AFC00241F4AE600389AF3 /* YApiHelper.swift */; };
1921
C94AFC04241F4E8A00389AF3 /* YApiObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = C94AFC03241F4E8A00389AF3 /* YApiObject.swift */; };
2022
C961C1DE23D82A8D008D0DE6 /* ConfigViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C961C1DD23D82A8D008D0DE6 /* ConfigViewController.swift */; };
@@ -68,6 +70,8 @@
6870
/* Begin PBXFileReference section */
6971
C92A970524E50D5900C87CCD /* YApiObjectTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YApiObjectTest.swift; sourceTree = "<group>"; };
7072
C92A971C24E514FB00C87CCD /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
73+
C935B49B24EA24BE00E48231 /* JSONHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONHelper.swift; sourceTree = "<group>"; };
74+
C935B49D24EA56EF00E48231 /* JSONHelperTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONHelperTest.swift; sourceTree = "<group>"; };
7175
C94AFC00241F4AE600389AF3 /* YApiHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YApiHelper.swift; sourceTree = "<group>"; };
7276
C94AFC03241F4E8A00389AF3 /* YApiObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YApiObject.swift; sourceTree = "<group>"; };
7377
C961C1DD23D82A8D008D0DE6 /* ConfigViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigViewController.swift; sourceTree = "<group>"; };
@@ -152,6 +156,7 @@
152156
isa = PBXGroup;
153157
children = (
154158
C92A970524E50D5900C87CCD /* YApiObjectTest.swift */,
159+
C935B49D24EA56EF00E48231 /* JSONHelperTest.swift */,
155160
);
156161
path = SwiftJSONModelerTest;
157162
sourceTree = "<group>";
@@ -191,6 +196,7 @@
191196
C961C1DD23D82A8D008D0DE6 /* ConfigViewController.swift */,
192197
C9DE045E242C8535008A0070 /* Config.swift */,
193198
C9CB247F241F559C00F4D5CE /* ErrorCenter.swift */,
199+
C935B49B24EA24BE00E48231 /* JSONHelper.swift */,
194200
);
195201
path = "SwiftJSONModeler For Xcode";
196202
sourceTree = "<group>";
@@ -344,6 +350,7 @@
344350
isa = PBXSourcesBuildPhase;
345351
buildActionMask = 2147483647;
346352
files = (
353+
C935B49E24EA56EF00E48231 /* JSONHelperTest.swift in Sources */,
347354
C9D04F2B242F218200843DC4 /* SwiftJSONModeler_For_XcodeTests.swift in Sources */,
348355
C92A970A24E512BD00C87CCD /* YApiObjectTest.swift in Sources */,
349356
);
@@ -361,6 +368,7 @@
361368
C92A971D24E514FB00C87CCD /* Constants.swift in Sources */,
362369
C92A971424E513EA00C87CCD /* YApiHelper.swift in Sources */,
363370
C9ED9CCA23D7F9B3004567A1 /* Document.swift in Sources */,
371+
C935B49C24EA24BE00E48231 /* JSONHelper.swift in Sources */,
364372
C961C1DE23D82A8D008D0DE6 /* ConfigViewController.swift in Sources */,
365373
C92A971524E513EA00C87CCD /* YApiObject.swift in Sources */,
366374
);

SwiftJSONModeler For Xcode/Base.lproj/Main.storyboard

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -749,9 +749,9 @@
749749
<constraint firstAttribute="width" constant="80" id="IgU-pX-0Ab"/>
750750
<constraint firstAttribute="height" constant="40" id="L1E-c2-3gR"/>
751751
</constraints>
752-
<buttonCell key="cell" type="push" title="Close" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="IQP-yP-yrb">
752+
<buttonCell key="cell" type="push" title="保存" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="IQP-yP-yrb">
753753
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
754-
<font key="font" metaFont="system" size="15"/>
754+
<font key="font" size="15" name=".PingFangSC-Regular"/>
755755
</buttonCell>
756756
<connections>
757757
<action selector="saveButtonTap:" target="5gI-5U-AMq" id="yhq-Ui-nvB"/>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//
2+
// JSONHelper.swift
3+
// SwiftJSONModeler For Xcode
4+
//
5+
// Created by Sven on 2020/8/17.
6+
// Copyright © 2020 Sven. All rights reserved.
7+
//
8+
/// 将 josn 转化为 YapiObject
9+
10+
import Foundation
11+
12+
public struct JSONHelper {
13+
/// 复制的文本
14+
var paste: String
15+
/// 将复制的文本 转化为 YApiObject 对象。
16+
func transform() -> YApiObject? {
17+
do {
18+
let dicJson = try JSONSerialization.jsonObject(with: paste.data(using: .utf8)!, options: .mutableLeaves)
19+
if let dic = dicJson as? [String: Any]{
20+
return objectOf(dic, key: "")
21+
} else if let arr = dicJson as? [Any] {
22+
return objectOf(arr, key: "")
23+
} else {
24+
return nil
25+
}
26+
} catch let e {
27+
print(e)
28+
ErrorCenter.shared.message = "json 序列化失败,请检查 json 数据"
29+
return nil
30+
31+
}
32+
}
33+
34+
/// 字典转对象
35+
/// - Parameter dic: 字典数据
36+
private func objectOf(_ dic: [String: Any], key: String) -> YApiObject {
37+
var childs: [YApiObject] = []
38+
for (label, value) in dic {
39+
let child = typeOf(label, value: value, parentKey: key)
40+
childs.append(child)
41+
}
42+
let object = YApiObject(parentKey: nil, key: key, mock: "", type: YApiType.object, typeRaw: "Object", des: "", childs: childs)
43+
return object
44+
}
45+
46+
/// 数组转对象
47+
/// - Parameter arry: 数据数组
48+
private func objectOf(_ arry: [Any], key:String) -> YApiObject {
49+
let type = YApiType.array
50+
guard let first = arry.first else {
51+
ErrorCenter.shared.message = "json 序列化 数组第一个元素类型判断异常"
52+
let childType = YApiType.undefined
53+
let objct = YApiObject(parentKey: key, key: key, mock: "", type: childType, typeRaw: "<#Undefined#>", des: nil, childs: [])
54+
let arrObjct = YApiObject(parentKey: key, key: key, mock: "", type: type, typeRaw: "Array", des: nil, childs: [objct])
55+
return arrObjct
56+
}
57+
let arrObjct = YApiObject(parentKey: nil, key: key, mock: "", type: type, typeRaw: "Array", des: nil, childs: [typeOf(nil, value: first)])
58+
return arrObjct
59+
}
60+
/// 类型数据类型判断
61+
/// - Parameter value: 值
62+
private func typeOf(_ key: String?, value: Any, parentKey: String? = nil) -> YApiObject {
63+
if value is NSNull {
64+
print("存在null")
65+
let type = YApiType.undefined
66+
let objct = YApiObject(parentKey: parentKey, key: key, mock: "", type: type, typeRaw: "<#NSNull#>", des: nil, childs: [])
67+
return objct
68+
} else if value is String {
69+
let type = YApiType.string
70+
let objct = YApiObject(parentKey: parentKey, key: key, mock: "", type: type, typeRaw: "String", des: nil, childs: [])
71+
return objct
72+
} else if value is Int {
73+
let type = YApiType.integer
74+
let objct = YApiObject(parentKey: parentKey, key: key, mock: "", type: type, typeRaw: "Int", des: nil, childs: [])
75+
return objct
76+
} else if value is Double {
77+
let type = YApiType.number
78+
let objct = YApiObject(parentKey: parentKey, key: key, mock: "", type: type, typeRaw: "Double", des: nil, childs: [])
79+
return objct
80+
} else if value is Bool {
81+
let type = YApiType.boolean
82+
let objct = YApiObject(parentKey: parentKey, key: key, mock: "", type: type, typeRaw: "Bool", des: nil, childs: [])
83+
return objct
84+
} else if let arr = value as? [Any] {
85+
return objectOf(arr, key: key ?? "")
86+
} else if let dic = value as? [String: Any]{
87+
return objectOf(dic, key: key ?? "")
88+
} else {
89+
ErrorCenter.shared.message = "json 格式异常,无法解析为 model"
90+
return YApiObject()
91+
}
92+
}
93+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
//
2+
// JSONHelperTest.swift
3+
// SwiftJSONModeler For XcodeTests
4+
//
5+
// Created by Sven on 2020/8/17.
6+
// Copyright © 2020 Sven. All rights reserved.
7+
//
8+
9+
import XCTest
10+
@testable import SwiftJSONModeler_For_Xcode
11+
12+
class JSONHelperTest: XCTestCase {
13+
14+
override func setUpWithError() throws {
15+
// Put setup code here. This method is called before the invocation of each test method in the class.
16+
}
17+
18+
override func tearDownWithError() throws {
19+
// Put teardown code here. This method is called after the invocation of each test method in the class.
20+
}
21+
22+
func testExample() throws {
23+
// This is an example of a functional test case.
24+
// Use XCTAssert and related functions to verify your tests produce the correct results.
25+
}
26+
27+
func testPerformanceExample() throws {
28+
// This is an example of a performance test case.
29+
self.measure {
30+
// Put the code you want to measure the time of here.
31+
}
32+
}
33+
34+
/// 测试异常 json 格式
35+
func testAbnormalJSON() -> Void {
36+
let json = """
37+
{
38+
"title": "这不是一个正确的 json",
39+
"property1": "第一个属性" // 不加逗号
40+
property: "" // 没用引号
41+
}
42+
"""
43+
let helper = JSONHelper(paste: json)
44+
let object = helper.transform()
45+
XCTAssertNil(object)
46+
}
47+
48+
/// 测试 第一层为数组 json
49+
func testArrayJSON() {
50+
let json =
51+
"""
52+
[
53+
"value1",
54+
"value2",
55+
"value3"
56+
]
57+
"""
58+
let helper = JSONHelper(paste: json)
59+
let object = helper.transform()
60+
XCTAssertNotNil(object)
61+
XCTAssert(object!.childs.first!.type == YApiType.string, "数组类型应该为 String")
62+
}
63+
64+
/// 测试 数组为空情况
65+
func testEmptyArray() {
66+
let json =
67+
"""
68+
{
69+
"title": "空数组",
70+
"emptyArray": []
71+
}
72+
"""
73+
let helper = JSONHelper(paste: json)
74+
let object = helper.transform()
75+
XCTAssertNotNil(object)
76+
XCTAssert(object!.childs.filter { $0.key == "emptyArray" }.first!.childs.first!.type == YApiType.undefined, "数组类型应该为 Undefined")
77+
}
78+
79+
/// 测试 单层 接送
80+
func testSingleJSON() -> Void {
81+
let json =
82+
"""
83+
{
84+
"title": "第一层 json",
85+
"stringValue": "字符串值",
86+
"intValue": 58,
87+
"doubleValue": 18.2,
88+
"nullValue": null,
89+
"boolValue": true
90+
}
91+
"""
92+
let helper = JSONHelper(paste: json)
93+
let object = helper.transform()
94+
XCTAssertNotNil(object)
95+
let objc = object!
96+
97+
XCTAssertNotNil(objc.childs.filter { $0.key == "stringValue" }.first)
98+
XCTAssertNotNil(objc.childs.filter { $0.key == "intValue" }.first)
99+
XCTAssertNotNil(objc.childs.filter { $0.key == "boolValue" }.first)
100+
XCTAssertNotNil(objc.childs.filter { $0.key == "nullValue" }.first)
101+
XCTAssertNotNil(objc.childs.filter { $0.key == "doubleValue" }.first)
102+
103+
}
104+
105+
/// 测试多层嵌套 json
106+
func testMultiLevelJSON() -> Void {
107+
let json =
108+
"""
109+
{
110+
"title": "第一层 json",
111+
"stringValue": "字符串值",
112+
"intValue": 58,
113+
"doubleValue": 18.2,
114+
"nullValue": null,
115+
"boolValue": true,
116+
"subJson": {
117+
"title": "第二层 json",
118+
"stringValue": "字符串值"
119+
},
120+
"arrayValue1": [
121+
"value1",
122+
"value2",
123+
"value3"
124+
],
125+
"arrayValue2": [{
126+
"title": "数组包含子 json",
127+
"intValue": 12,
128+
"boolValue": false
129+
}]
130+
}
131+
"""
132+
let helper = JSONHelper(paste: json)
133+
let object = helper.transform()
134+
XCTAssertNotNil(object)
135+
guard object != nil else {
136+
return
137+
}
138+
let subJsonArr = object!.childs.filter{ $0.key == "subJson" }
139+
XCTAssertNotNil(subJsonArr.first)
140+
guard let subJson = subJsonArr.first else {
141+
return
142+
}
143+
XCTAssert(subJson.childs.count == 2, "subJson 属性数量为2")
144+
XCTAssert(object!.childs.filter { $0.key == "arrayValue1" }.first!.childs.first!.type == YApiType.string, "arrayValue1 数组类型应该为 String")
145+
XCTAssert(object!.childs.filter { $0.key == "arrayValue2" }.first!.childs.first!.type == YApiType.object, "arrayValue2 数组类型应该为 object")
146+
}
147+
148+
}

0 commit comments

Comments
 (0)