XMLCoder
XMLCoder copied to clipboard
UnkeyedEncodingContainer results in incorrect XML string
There's some bugs hadling ordered arrays i.e. unkeyed containers. Let's say, I have a tree with some nodes.
let tree = TreeNode()
// create sub node with a child
let subNode1 = TreeNode()
let subSubNode1 = TreeNode()
subNode1.addChild(subSubNode1)
// create another sub node with a child
let subNode2 = TreeNode()
let subSubNode2 = TreeNode()
subNode2.addChild(subSubNode2)
// add children to that child
let subSubSubNode1 = TreeNode()
let subSubSubNode2 = TreeNode()
subSubNode2(subSubSubNode1)
subSubNode2(subSubSubNode2)
// now add all of that to the tree
tree.addChild(subNode1)
tree.addChild(subNode2)
Now I'm encoding the tree as array of arrays.
func encode(to encoder: Encoder) throws {
var nodeContainer = encoder.container(keyedBy: OutlineTree.CodingKeys.self)
try nodeContainer.encode(element, forKey: .node)
guard !children.isEmpty else { return }
var childrenContainer = nodeContainer.nestedUnkeyedContainer(forKey: .children)
try children.forEach{ try childrenContainer.encode($0) }
}
The tree is stored in some Project object which is encoded like this:
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(identifier, forKey: .identifier)
var contentContainer = container.nestedUnkeyedContainer(forKey: .content)
try content.rootTree.children.forEach{ try contentContainer.encode($0) }
}
So, here's the problem. If I use builtin JSONEncoder everything is fine. I get this string:
{
"identifier" : "7A71AE91-D0F6-4837-9E66-3C9E4FF06702",
"content" : [
{
"node" : {
"type" : "subNode1",
},
"children" : [
{
"node" : {
"type" : "subSubNode1",
}
}
]
},
{
"node" : {
"type" : "subNode2",
},
"children" : [
{
"node" : {
"type" : "subSubNode2",
},
"children" : [
{
"node" : {
"type" : "subSubSubNode1",
}
},
{
"node" : {
"type" : "subSubSubNode2",
}
}
]
}
]
}
]
}
But if I'm using the XMLEncoder, I'm gettin the messed up string:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<content>
<node type="subNode1" />
<children>
<node type="subSubNode1" />
</children>
</content>
<content>
<node type="subNode2" />
<children>
<node type="subSubNode2" />
<children>
<node type="subSubSubNode1" />
</children>
<children>
<node type="subSubSubNode2" />
</children>
</children>
</content>
</project>
It creates a key for every item in an array which is wrong, as far as I understand. It should create a key for an unkeyed container as a whole instead of keying every item in the container with that key.
P.S.: that XML string is impossible to decode correctly.