How to convert all lists to sets when json file is loaded
<p>I have json files that look like this:</p>

<pre><code>{
    "K1": {
        "p": [
            "A"
        ], 
        "s": [
            "B", 
            "C"
        ]
    }, 
    "K2": {
        "p": [
            "A", 
            "F"
        ], 
        "s": [
            "G", 
            "H",
            "J"
        ]
    }
}
</code></pre>

<p>I can easily read in this data:</p>

<pre><code>import json

with open('json_lists_to_sets.json') as fi:
    data = json.load(fi)
</code></pre>

<p>Then <code>data</code> looks as follows:</p>

<pre><code>{u'K2': {u'p': [u'A', u'F'], u's': [u'G', u'H', u'J']}, u'K1': {u'p': [u'A'], u's': [u'B', u'C']}}
</code></pre>

<p>For my further analysis, however, it would be better to use <code>sets</code> instead of <code>lists</code>. I can of course convert <code>lists</code> to <code>sets</code> after I have read in the data:</p>

<pre><code>for vi in data.values():
    vi['p'] = set(vi['p'])
    vi['s'] = set(vi['s'])
</code></pre>

<p>which gives me the desired output:</p>

<pre><code>print data['K2']
</code></pre>

<p>yields</p>

<pre><code>{u'p': {u'A', u'F'}, u's': {u'G', u'H', u'J'}}
</code></pre>

<p>My questions is whether I can convert these <code>lists</code> to <code>sets</code> directly when I read in the data in the <code>json.load</code> command, so something like "convert all lists you find to sets". Does something like this exist?</p>

<p>Although the <code>json</code> library offers many hooks to alter decoding, there is no hook to hook into loading a JSON array.</p>

<p>You'll have to recursively update the decoded result afterwards instead:</p>

<pre><code>def to_sets(o):
    if isinstance(o, list):
        return {to_sets(v) for v in o}
    elif isinstance(o, dict):
        return {k: to_sets(v) for k, v in o.items()}
    return o
</code></pre>

<p>This handles lists at any nested dictionary depth:</p>

<pre><code>&gt;&gt;&gt; to_sets(data)
{u'K2': {u'p': set([u'A', u'F']), u's': set([u'H', u'J', u'G'])}, u'K1': {u'p': set([u'A']), u's': set([u'C', u'B'])}}
</code></pre>

<p>Take into account however, that lists containing other dictionaries <em>can't</em> be handled because dictionaries are not hashable.</p>

<p>If you expect to find lists nested inside other lists, you'd have to switch to using a <code>frozenset()</code> rather than a <code>set()</code> to be able to nest those:</p>

<pre><code>def to_sets(o):
    if isinstance(o, list):
        return frozenset(to_sets(v) for v in o)
    elif isinstance(o, dict):
        return {k: to_sets(v) for k, v in o.items()}
    return o
</code></pre>

python json