Bunny83 / SimpleJSON

A simple JSON parser in C#
MIT License
735 stars 294 forks source link

Merging two JSON nodes #48

Open ratkingsminion opened 2 years ago

ratkingsminion commented 2 years ago

I have my data split over several files and I wondered if there's an easy way to merge the JSONs, or if I have to iterate over all keys myself.

Bunny83 commented 2 years ago

Interesting case. No, at the moment there's no real way to merge two nodes. Also if there were, the question is how it should work specifically for arrays or objects. For example if you merge two objects and they have overlapping keys, which should take precedence? The best solution may be to add an AddRange method (like List has) so you can add the node content to another collection node.

So yes, as a workaround you have to iterate through the keys yourself

foreach(var kv in node2)
    node1[kv.Key] = kv.Value;

This assumes we talk about two object nodes and we add thekeys / values of node2 to node1. If there are overlapping keys, node2 would take precedence and overwrite those in node1. Note that foreach can be used garbage free since JSONNode has a struct enumerator. Though of course adding new elements to a node would require more memory. Be careful when adding the same JSONNode to several nodes at the same time. The nodes are not duplicated. So both nodes would contain references to the same nodes when simply added like that. At the moment there's no deep copy method, though I may add one in the future.

ratkingsminion commented 2 years ago

I see, thanks for the information. Right now I merge the nodes recursively, to mitigate the problem with overwriting a bit.

    void MergeNodes(JSONNode to, JSONNode source) {
        foreach (var kvp in source) {
            if (to.HasKey(kvp.Key)) { MergeNodes(to[kvp.Key], kvp.Value); }
            else { to.Add(kvp.Key, kvp.Value); }
        }
}

But yeah, I didn't think of shared nodes problem. A deep copy would be useful then.

mironek commented 2 years ago

Hi,

I was looking for a way to inject JSON into another JSON in a specific place (at specyfic index if elements are array based) and I came up with such a function - maybe it will be useful to someone.

public JSONNode InsertToJSON(JSONNode _sourceNode, JSONNode _injectionNode, int _insertIndex = -1){
    if(_sourceNode != null){
        if(_injectionNode != null){
            if(_insertIndex != -1 && _insertIndex < _sourceNode.Count){
                JSONNode _tempNode = JSON.Parse("[]");
                for(int _i = 0; _i < _sourceNode.Count; _i++){  
                    if(_i == _insertIndex){
                        _tempNode.Add(_injectionNode);
                    }                           
                    _tempNode.Add(_sourceNode[_i]); 
                }
                _sourceNode = _tempNode;
            }
            else{
                _sourceNode.Add(_injectionNode);
            }
        }
        else{
            Debug.LogWarning("Injection JSONNode is missing.");
        }
    }
    else{
        Debug.LogWarning("Source JSONNode is missing.");
    }
    return _sourceNode;
}

It works fine for array based source node and only on 1st level. However, idt does not take into account shared names if a given Node has named objects.