In this blog post, we explain how we used a Markov chain to detect whether a JSON object represents a class (fixed properties) or a map (dynamic keys) to infer its type and generate the same code a human programmer would for representing that data.<p>For example, given this Bitcoin API data:<p><pre><code> {
"0000000000000000000e222e4e7afc29c49f6398783a94c846dee2e13c6408f5": {
"size": 969709,
"height": 510599,
"difficulty": 3007383866429.732,
"previous": "000000000000000000552a7783efd39eaa1c5ff6789e21a0bbe7547bc454fced"
},
"000000000000000000552a7783efd39eaa1c5ff6789e21a0bbe7547bc454fced": {
"size": 991394,
"height": 510598,
"difficulty": 3007383866429.732,
"previous": "00000000000000000043aba4c065d4d92aec529566287ebec5fe9010246c9589"
},
"00000000000000000043aba4c065d4d92aec529566287ebec5fe9010246c9589": {
"size": 990527,
"height": 510597,
"difficulty": 3007383866429.732,
"previous": "00000000000000000009025b9e95911a4dc050de129ea4eb5e40ef280751a0cb"
}
}
</code></pre>
You'd expect the corresponding Swift code:<p><pre><code> typealias Blocks = [String: Block] // a.k.a. Dictionary<String, Block>
struct Block {
let size, height: Int
let difficulty: Double
let previous: String
}
</code></pre>
Rather than:<p><pre><code> struct Blocks {
let _0000000000000000000e222e4e7afc29c49f6398783a94c846dee2e13c6408f5: Block
let _00000000000000000043aba4c065d4d92aec529566287ebec5fe9010246c9589: Block
let _00000000000000000009025b9e95911a4dc050de129ea4eb5e40ef280751a0cb: Block
}
struct Block {
let size, height: Int
let difficulty: Double
let previous: String
}
</code></pre>
We taught quicktype to make the same decision by evaluating the JSON property names with a Markov chain trained on simulated class property names. Our blog article goes into detail and lets you play with our Markov chain!