Search code examples
pythonjsonsimplejson

Decode json arrays to frozensets


I have a nested json array, and I want to decode the arrays to to frozensets instead of lists.

import json
class FrozensetDecoder(json.JSONDecoder): 
    def default(self, obj): 
        print(obj) 
        if isinstance(obj, list): 
            return frozenset(obj) 
        return obj 
    array = list = default 


In [8]: json.loads('[1,[2],3]', cls=FrozensetDecoder)                                                                                                                                                                                                                                                  
Out[8]: [1, [2], 3]

But I want

frozenset({1, frozenset({2}), 3})

Solution

  • I'm not familiar with the approach you're taking by redefining array and list as a default function.

    Here's some code that does what you want though:

    import json
    from json import scanner
    
    
    class MyDecoder(json.JSONDecoder):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            # set up an alternative function for parsing arrays
            self.previous_parse_array = self.parse_array
            self.parse_array = self.json_array_frozenset
            # ensure that the replaced function gets used
            self.scan_once = scanner.py_make_scanner(self)
    
        def json_array_frozenset(self, s_and_end, scan_once, **kwargs):
            # call the parse_array that would have been used previously
            values, end = self.previous_parse_array(s_and_end, scan_once, **kwargs)
            # return the same result, but turn the `values` into a frozenset
            return frozenset(values), end
    
    
    data = json.loads('[1,[2],3]', cls=MyDecoder)
    print(data)
    

    Note that the result will be frozenset({1, 3, frozenset({2})}) and not frozenset({1, frozenset({2}), 3}) but since sets are unordered, that shouldn't matter.