Constructor bug (re JSON)

Issue #3 new
Jonathan Eunice created an issue

Here is what appears to be a stuf constructor bug:

>>> j = '{"this": [ {"and": 1} , {"and":2}, {"and":3}] }'
>>> import json
>>> json.loads(j)
{u'this': [{u'and': 1}, {u'and': 2}, {u'and': 3}]}

So far so good. Python logical equivalence to JSON structure. How about with OrderedDict?

>>> from collections import OrderedDict
>>> json.loads(j, object_pairs_hook=OrderedDict)
OrderedDict([(u'this', [OrderedDict([(u'and', 1)]), OrderedDict([(u'and', 2)]), OrderedDict([(u'and', 3)])])])

Great. How about with stuf?

>>> from stuf import stuf
>>> json.loads(j, object_pairs_hook=stuf)
stuf(this=stuf(and=3))

Not so much. Somehow stuf collapses down three parallel mappings into a single mapping, and erases the intervening array.

I thought I might work around the problem by converting to dict first:

>>> stuffer = lambda x: stuf(dict(x))
>>> json.loads(j, object_pairs_hook=stuffer)

But that gives me the same thing as when stuf is the hook itself. (Just for completeness, dict as an explicit hook works fine, like the default case.)

Comments (2)

  1. Jonathan Eunice reporter

    I did work around it with a factory function:

    def stufize(d):
        if isinstance(d, list):
            return [ stufize(item) for item in d ]
        elif isinstance(d, dict):
            result = stuf()
            for k,v in d.items():
                result[k] = stufize(v)
            return result
        else:
            return d
    

    But that seems a little grotesque.

  2. Jonathan Eunice reporter

    I was not able to make an on-the-fly workaround. Probably because when it's boiled down, stuf really doesn't like encoding lists of stuf objects that have the same keys:

    With dissimilar sub-keys, no problem:

    >>> stuf(all=[stuf(a=1),stuf(b=2), stuf(c=3)])
    stuf(all=stuf(a=1, c=3, b=2))
    

    But with similar sub-keys, BOOM! Breakage and wrong results.

    >>> stuf(all=[stuf(a=1),stuf(a=2), stuf(a=3)])
    stuf(all=stuf(a=3))
    
  3. Log in to comment