nixzhu / Ananda

JSON model decoding based on yyjson.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ananda

JSON model decoding based on yyjson.

Example

We have JSON as follow:

{
  "profile": {
    "nickname": "NIX",
    "username": "@nixzhu@mastodon.social",
    "avatar_url": "https://files.mastodon.social/accounts/avatars/109/329/064/034/222/219/original/371901c6daa01207.png"
  },
  "toots": [
    {
      "id": 1,
      "content": "Hello World!",
      "created_at": "1674127714"
    },
    {
      "id": 2,
      "content": "How do you do?",
      "created_at": "1674127720"
    }
  ]
}

And we create models conforms to AnandaModel protocol as follow:

import Foundation
import Ananda

struct Mastodon: AnandaModel {
    let profile: Profile
    let toots: [Toot]

    init(json: AnandaJSON) {
        profile = .init(json: json.profile)
        toots = json.toots.array().map { .init(json: $0) }
    }
}

extension Mastodon {
    struct Profile: AnandaModel {
        let nickname: String
        let username: String
        let avatarURL: URL

        init(json: AnandaJSON) {
            username = json.username.string()
            nickname = json.nickname.string()
            avatarURL = json.avatar_url.url()
        }
    }
}

extension Mastodon {
    struct Toot: AnandaModel {
        let id: Int
        let content: String
        let createdAt: Date

        init(json: AnandaJSON) {
            id = json.id.int()
            content = json.content.string()
            createdAt = json.created_at.date()
        }
    }
}

Then, we can decode a Mastodon as follow:

let mastodon = Mastodon.decode(from: jsonString)

Or

let mastodon = Mastodon.decode(from: jsonData)

If you only want to decode a part of the JSON, like profile, use the path to specify it as follow:

let profile = Mastodon.Profile.decode(from: jsonData, path: ["profile"])

How about just decode toots? It's an array, do it as follow:

let toots = [Mastodon.Toot].decode(from: jsonData, path: ["toots"])

Swift Macro

With Swift 5.9 and AnandaMacros, you can use macro to eliminate the initialization methods as follow:

import Foundation
import Ananda
import AnandaMacros

@AnandaInit
struct Mastodon: AnandaModel {
    let profile: Profile
    let toots: [Toot]
}

extension Mastodon {
    @AnandaInit
    struct Profile: AnandaModel {
        let nickname: String
        let username: String
        @AnandaKey("avatar_url")
        let avatarURL: URL
    }
}

extension Mastodon {
    @AnandaInit
    struct Toot: AnandaModel {
        let id: Int
        let content: String
        @AnandaKey("created_at")
        let createdAt: Date
    }
}

Simple and clean, right?

Benchmark

See AnandaBenchmark.

Tool

You may use Ducky Model Editor to generate AnandaModel from JSON to save your time.

Ducky Model Editor

Ducky Model Editor

About

JSON model decoding based on yyjson.

License:MIT License


Languages

Language:Swift 100.0%