Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DynamicNodeEncoding Works with List Type, but Not with List's Element Type #216

Open
owenzhao opened this issue Apr 6, 2021 · 2 comments

Comments

@owenzhao
Copy link
Collaborator

owenzhao commented Apr 6, 2021

// Model

class Foo:Object, Codable, DynamicNodeEncoding {
    enum CodingKeys: String, CodingKey {
        case id
        case numbers = "number"
    }

    static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
        switch key {
        case CodingKeys.id:
            return .attribute
        default:
            return .element
        }
    }

    @objc dynamic var id = ObjectId.generate()
    let numbers = List<Bar>()

    override class func primaryKey() -> String? {
        return "id"
    }
}

class Bar:Object, Codable, DynamicNodeEncoding {
    enum CodingKeys: String, CodingKey {
        case id
    }

    static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
        switch key {
        case CodingKeys.id:
            return .attribute
        default:
            return .element
        }
    }

    @objc dynamic var id = ObjectId.generate()

    override class func primaryKey() -> String? {
        return "id"
    }
}
// code

let foo = Foo()
foo.numbers.append(objectsIn:[Bar(),Bar(),Bar()])

let encoder = XMLEncoder()
encoder.outputFormatting = .prettyPrinted
let encodedXML = try! encoder.encode(foo, withRootKey: "foo")

let str = String(data: encodedXML, encoding: .utf8)
print(str!)

Results:

<foo id="606bedefcd66ce1115c94be3">
    <number>
        <id>606bedefcd66ce1115c94be6</id>
    </number>
    <number>
        <id>606bedefcd66ce1115c94be7</id>
    </number>
    <number>
        <id>606bedefcd66ce1115c94be8</id>
    </number>
</foo>

Expected:
The ids in number should be attributes instead of elements.

If I change let numbers = List<Bar>() to var numbers = [Bar](), the issue is gone. So I think there must be something wrong here and I don't know what to do next. As the Realm requests to use List instead of Array here. Any suggestions?

@owenzhao
Copy link
Collaborator Author

owenzhao commented Apr 6, 2021

List

截屏2021-04-06 下午1 28 19

@owenzhao
Copy link
Collaborator Author

owenzhao commented Apr 6, 2021

Solved. I read the source code of XMLCoder, and in DynamicNodeEncoding.swift, there is

extension Array: DynamicNodeEncoding where Element: DynamicNodeEncoding {
    public static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
        return Element.nodeEncoding(for: key)
    }
}

So I make it as a copy for List

extension List: DynamicNodeEncoding where Element: DynamicNodeEncoding {
    public static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
        return Element.nodeEncoding(for: key)
    }
}
// results

<foo id="606bf34ba0066ab968b69b2b">
    <number id="606bf34ba0066ab968b69b2e" />
    <number id="606bf34ba0066ab968b69b2f" />
    <number id="606bf34ba0066ab968b69b30" />
</foo>

And it worked. So I guess for people who use Realm, you should do this too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant