Skip to content

这是一个原生增强版json解析库,不需要更改遵循Codable协议,完美符合官方

License

Notifications You must be signed in to change notification settings

ZClee128/ZCJSON

Repository files navigation

ZCJSON

CI Status Version License Platform

中文文档

ZCJSON is a powerful JSON parsing library for Swift that extends Codable with additional features like default values, type conversion, and Any type handling.

Features

  • 🎯 Automatic default values for missing fields
  • 🔄 String to number conversion
  • 📦 Any type handling (dictionaries and arrays)
  • 🚫 Field ignoring with annotations
  • 👥 Inheritance support
  • 🎲 Enum handling with default cases
  • 🏗️ Macro support for code generation

Installation

CocoaPods

ZCJSON is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'ZCJSON'

Swift Package Manager

ZCJSON supports installation via Swift Package Manager. In Xcode:

  1. Select File > Add Packages...
  2. Enter the package URL: https://github.com/ZClee128/ZCJSON.git
  3. Choose version rules (Up to Next Major recommended)
  4. Click Add Package

Or add the dependency directly in your Package.swift:

dependencies: [
    .package(url: "https://github.com/ZClee128/ZCJSON.git", from: "1.0.0")
]

Usage

Basic JSON Parsing

// Dictionary to model
let model = data.asDecodable(Model.self)

// Model to JSON string
model.toJSONString()

// Parse with designated path
let jsonString = """
{
    "code": 200,
    "msg": "success",
    "data": {
        "cat": {
            "id": 12345,
            "name": "Kitty"
        }
    }
}
"""

struct Cat: Codable {
    var id: Int64
    var name: String
}

if let cat = jsonString.asDecodable(Cat.self, designatedPath: "data.cat") {
    print(cat.name) // Prints "Kitty"
}

Default Values

ZCJSON provides default values for missing fields in your JSON:

struct User: Codable {
    let name: String
    let age: Int  // Will be 0 if missing
    @Default<Bool.False>
    var isActive: Bool  // Will be false if missing
    @Default<Bool.True>
    var isVerified: Bool  // Will be true if missing
}

String to Number Conversion

Automatically converts string numbers to numeric types:

struct Product: Codable {
    let id: Int        // "123" -> 123
    let price: CGFloat // "99.99" -> 99.99
}

Any Type Handling

Handle dynamic JSON structures with Any type:

@zcCodable
struct DynamicModel: Codable {
    var data: [String: Any]
    var items: [Any]
}

Field Ignoring

Ignore specific fields during parsing:

struct User: Codable {
    @zcAnnotation(key: ["password"], ignore: true)
    var password: String = "default"
}

Enum Handling

Handle enums with default cases:

enum Status: String, Codable, CaseDefaultsFirst {
    case active
    case inactive
    case pending
}

struct TestModel: Codable {
    var status: Status
}

let jsonString = """
{
    "status": "invalid"  // Will default to first case
}
"""

if let decoded = jsonData.asDecodable(TestModel.self) {
    XCTAssertEqual(decoded.status, .active)  // Defaults to first case
}

Enum with Int Values

Handle enums with integer values:

enum TestType: Int, Codable, CaseDefaultsFirst {
    case none = -1
    case one = 1
}

struct TestModel: Codable {
    let name: String
    let age: Int
    let type: TestType
}

let jsonString = """
{
    "name": "aa",
    "age": "10",
    "type": 1
}
"""

if let decoded = jsonData.asDecodable(TestModel.self) {
    XCTAssertEqual(decoded.name, "aa")
    XCTAssertEqual(decoded.age, 10)
    XCTAssertEqual(decoded.type, .one)  // Parses integer value to enum case
}

Inheritance Support

Support for class inheritance in JSON parsing:

class BaseModel: Codable {
    var name: String
}

@zcInherit
class UserModel: BaseModel {
    var age: Int
}

Advanced Examples

Complex Model with Multiple Features

@zcCodable
struct ComplexModel: Codable {
    // Default values
    @Default<Bool.True>
    var isEnabled: Bool
    
    // String to number conversion
    let count: Int
    
    // Any type handling
    var metadata: [String: Any]
    var items: [Any]
    
    // Enum with default case
    var status: Status
    
    // Ignored field
    @zcAnnotation(key: ["internal"], ignore: true)
    var internalData: String = "default"
}

Unit Tests

ZCJSON includes comprehensive unit tests covering:

  • ✅ Default value handling
  • ✅ Type conversion
  • ✅ Any type parsing
  • ✅ Field ignoring
  • ✅ Inheritance
  • ✅ Enum handling

Run tests using ⌘U or Product -> Test to verify functionality.

Author

ZClee128, 876231865@qq.com

License

ZCJSON is available under the MIT license. See the LICENSE file for more info.

Support

If you encounter any parsing issues or have questions, feel free to contact me or join our QQ group: 982321096

🧪 Unit Test Coverage

ZCJSON comes with extensive unit tests that cover common JSON parsing scenarios, including but not limited to:

  • ✅ Default value fallback when fields are missing (Int, Float, Bool, String, etc.)
  • ✅ Type conversion from strings to numbers: e.g. "10"Int, CGFloat, Double
  • ✅ Supports hybrid model decoding of [String: Any] and [Any]
  • ✅ Graceful decoding of dynamic Any values
  • ✅ Declarative default values via the @Default property wrapper
  • ✅ Extended default support for numeric types: UInt8/16/32/64, Int8/16/32/64
  • ✅ Enum fallback decoding with CaseDefaultsFirst
  • ✅ Field ignoring and key remapping via @zcAnnotation
  • ✅ Compatibility between macro-generated models and manually implemented models

💡 Example: See Tests.swift for full use of .asDecodable() and validation of @zcCodable error-tolerant decoding behavior.

Run tests via ⌘U or Product -> Test to verify parsing stability and behavior.

Unit Test Examples

Default Value Handling

ZCJSON automatically handles missing fields with appropriate default values:

// Test missing field with default value
struct TestModel: Codable {
    let name: String
    let age: Int  // Will be 0 if missing
}

let jsonString = """
{
    "name": "Alice"
}
"""

if let decoded = jsonData.asDecodable(TestModel.self) {
    XCTAssertEqual(decoded.name, "Alice")
    XCTAssertEqual(decoded.age, 0)  // Default value for missing field
}

Custom Default Values

You can specify custom default values using @Default:

struct TestModel: Codable {
    let name: String
    let age: CGFloat
    @Default<Bool.False>
    var isStudent: Bool
    @Default<Bool.True>
    var isTeacher: Bool
}

let jsonString = """
{
    "name": "Alice"
}
"""

if let decoded = jsonData.asDecodable(TestModel.self) {
    XCTAssertEqual(decoded.name, "Alice")
    XCTAssertEqual(decoded.age, 0.0)
    XCTAssertEqual(decoded.isStudent, false)  // Custom default
    XCTAssertEqual(decoded.isTeacher, true)   // Custom default
}

String to Number Conversion

Automatic conversion from string to numeric types:

struct TestModel: Codable {
    let age: Int
    let age1: CGFloat
}

let jsonString = """
{
    "age": "10",
    "age1": "10.0"
}
"""

if let decoded = jsonData.asDecodable(TestModel.self) {
    XCTAssertEqual(decoded.age, 10)      // String "10" converted to Int
    XCTAssertEqual(decoded.age1, 10.0)   // String "10.0" converted to CGFloat
}

Any Type Handling

Handle dynamic JSON structures with Any type:

@zcCodable
struct TestAnyModel: Codable {
    var age: Any
    @zcAnnotation(key: ["age1"], ignore: true)
    var age1: Float = 40
    var data: [String: Any]
    var arr: [Any]
}

let jsonString = """
{
    "age": "10",
    "age1": "10.0",
    "data": {
        "a": 1,
        "b": "2"
    },
    "arr": ["1", "2"]
}
"""

if let decoded = jsonData.asDecodable(TestAnyModel.self) {
    XCTAssertEqual(decoded.age as! String, "10")
    XCTAssertEqual(decoded.age1, 40.0)  // Ignored field with default value
    XCTAssertEqual(decoded.data["a"] as? Int, 1)
    XCTAssertEqual(decoded.data["b"] as? String, "2")
    XCTAssertEqual(decoded.arr as? [String], ["1", "2"])
}

Field Ignoring

Ignore specific fields during parsing:

@zcCodable
struct TestAnyModel: Codable {
    @zcAnnotation(key: ["age1"], ignore: true)
    var age1: Float = 40
    var data: [String: Any]
}

let jsonString = """
{
    "age1": "10.0",
    "data": {
        "a": 1,
        "b": "2"
    }
}
"""

if let decoded = jsonData.asDecodable(TestAnyModel.self) {
    XCTAssertEqual(decoded.age1, 40.0)  // Ignored field keeps default value
    XCTAssertEqual(decoded.data["a"] as? Int, 1)
}

Inheritance Support

Support for class inheritance in JSON parsing:

class BaseModel: Codable {
    var name: String
}

@zcInherit
class OneModel: BaseModel {
    var age: Int
}

let jsonString = """
{
    "name": "aa",
    "age": "10"
}
"""

if let decoded = jsonData.asDecodable(OneModel.self) {
    XCTAssertEqual(decoded.name, "aa")
    XCTAssertEqual(decoded.age, 10)
}

Enum Handling

Handle enums with default cases:

enum Status: String, Codable, CaseDefaultsFirst {
    case active
    case inactive
    case pending
}

struct TestModel: Codable {
    var status: Status
}

let jsonString = """
{
    "status": "invalid"  // Will default to first case
}
"""

if let decoded = jsonData.asDecodable(TestModel.self) {
    XCTAssertEqual(decoded.status, .active)  // Defaults to first case
}

使用方


WECO

WEGAME
icon-1024
玉玄道

About

这是一个原生增强版json解析库,不需要更改遵循Codable协议,完美符合官方

Resources

License

Stars

Watchers

Forks

Packages

No packages published