avian2 / jsonmerge

Merge a series of JSON documents.
MIT License
214 stars 25 forks source link

Depth Affects Behavior of mergeStrategy="append" #60

Closed Rhiannon-Udall closed 1 year ago

Rhiannon-Udall commented 1 year ago

Hello,

I found this package today, and it seems like it should do exactly I want for a thorny input parsing problem. However, I found behavior which seems pathological at increased depth into the json. In particular:

merge_schema = {
    "properties" : {
        "g": {
            "properties":{
                "i": {
                    "mergeStrategy":"arrayMergeById",
                    "mergeOptions":{"idRef":'/uid'}
                },
                "h": {
                    "mergeStrategy":"append"
                }
            }
        },
        "n": {
            "properties":{
                "p": {
                    "properties": {
                        "r":{
                            "properties":{"mergeStrategy":"append"}
                        }
                    }
                }
            }
        }
    }
}

merger = Merger(merge_schema)

test_dict = \
{
    "g" : {
        "h" : [ "a", "b"],
        "i" : [
            {
                'uid' : "test1",
                "j" : 4,
            },
            {
                'uid' : "test2",
                "j" : 5,
            }
        ],
    },
    "n":{
        "o":4,
        "p":{
            "q" : 1,
            "r" : [
                "s",
                "t",
            ],
        }
    }
}
update_test_3 = {
    "g" : {
        "h": ["c"],
        "i" : [
            {'uid' : "test3",
            "j" : 11},
            {'uid' : "test1",
            "j" : 12}
        ]
    },
    "n" : {
        "p" : {
            "r":["u",],
        }
    }
}
expected_output = {
    "g": {
        "h": [
            "a",
            "b",
            "c"
        ],
        "i": [
            {
                "uid": "test1",
                "j": 12
            },
            {
                "uid": "test2",
                "j": 5
            },
            {
                "uid": "test3",
                "j": 11
            }
        ]
    },
    "n": {
        "o": 4,
        "p": {
            "q": 1,
            "r": [
                "s", "t", "u"
            ]
        }
    }
}
test_dict = merger.merge(test_dict, update_test_3)
print(test_dict == expected_output)
print(json.dumps(test_dict, indent=4))

yields

False
{
    "g": {
        "h": [
            "a",
            "b",
            "c"
        ],
        "i": [
            {
                "uid": "test1",
                "j": 12
            },
            {
                "uid": "test2",
                "j": 5
            },
            {
                "uid": "test3",
                "j": 11
            }
        ]
    },
    "n": {
        "o": 4,
        "p": {
            "q": 1,
            "r": [
                "u"
            ]
        }
    }
}

In particular, one may note that the append strategy seems to work correctly at one level of depth (g/h) but fails at another (n/p/r). Perhaps this is a subtlety of setting up the merge schema, though I am not sure what would be different between the first case and the second besides the depth.

avian2 commented 1 year ago

I am not sure what would be different between the first case and the second besides the depth.

Compare this part:

                      "r":{
                            "properties":{"mergeStrategy":"append"}
                        }

with this part:

                "h": {
                    "mergeStrategy":"append"
                }