API Docs

json_merger

class json_merger.Merger(root, head, update, default_dict_merge_op, default_list_merge_op, list_dict_ops=None, list_merge_ops=None, comparators=None, data_lists=None)[source]

Class that merges two JSON objects that share a common ancestor.

This class treats by default all lists as being lists of entities and offers support for matching their elements by their content, by specifing per-field comparator classes.

Parameters:
  • root – A common ancestor of the two objects being merged.
  • head – One of the objects that is being merged. Refers to the version that is currently in use. (e.g. a displayed database record)
  • update – The second object that is being merged. Refers to an update that needs to be integrated with the in-use version.
  • default_dict_merge_op
    (json_merger.config.DictMergerOps class attribute):
    Default strategy for merging regular non list JSON values (strings, numbers, other objects).
  • default_list_merge_op
    (json_merger.config.UnifierOps class attribute):
    Default strategy for merging two lists of entities.
  • dict_merge_ops

    Defines custom strategies for merging dict of entities.

    Dict formatted as:
  • list_merge_ops

    Defines custom strategies for merging lists of entities.

    Dict formatted as:
  • comparators

    Defines classes used for rendering entities in list fields as equal.

    Dict formatted as:
  • data_lists – List of config strings defining the lists that are not treated as lists of entities.

Note

A configuration string represents the path towards a list field in the object sepparated with dots.

Example

Configuration strings can be:

For {'lst': [{'id': 0, 'tags': ['foo', 'bar']}]}:

  • the config string for the top level list is 'lst'
  • the config string for the tags lists is 'lst.tags'

json_merger.config

class json_merger.config.DictMergerOps[source]

Possible strategies for merging two base values.

FALLBACK_KEEP_HEAD

In case of conflict keep the head value.

FALLBACK_KEEP_UPDATE

In case of conflict keep the update value.

class json_merger.config.UnifierOps[source]
KEEP_ONLY_HEAD_ENTITIES

Merge entities in update with their match in head having as a base the match in root.

KEEP_ONLY_UPDATE_ENTITIES

Merge entities in ‘head’ with their match in update having as a base the match in root.

KEEP_UPDATE_AND_HEAD_ENTITIES_HEAD_FIRST

Perform an union of all entities from head and update and merge the matching ones. Also, preserve the order relations between the entities in both lists. If two entities can have the same position first pick the one that is present in the head object.

KEEP_UPDATE_AND_HEAD_ENTITIES_UPDATE_FIRST

Same behavior as KEEP_UPDATE_AND_HEAD_ENTITIES_HEAD_FIRST but first pick the update entities.

KEEP_UPDATE_ENTITIES_CONFLICT_ON_HEAD_DELETE

If an entity was added in the diff between the root and head lists but it’s not present in the update list then raise a conflict.

json_merger.comparator

class json_merger.comparator.BaseComparator(l1, l2)[source]

Abstract base class for Entity Comparison.

Parameters:
  • l1 – First list of entities.
  • l2 – Second list of entities.
equal(obj1, obj2)[source]

Implementation of object equality.

get_matches(src, src_idx)[source]

Get elements equal to the idx’th in src from the other list.

e.g. get_matches(self, ‘l1’, 0) will return all elements from self.l2 matching with self.l1[0]

process_lists()[source]

Do any preprocessing of the lists.

class json_merger.comparator.DefaultComparator(l1, l2)[source]

Two objects are the same entity if they are fully equal.

Parameters:
  • l1 – First list of entities.
  • l2 – Second list of entities.
class json_merger.comparator.PrimaryKeyComparator(l1, l2)[source]

Considers two objects as equal if they have the same primary key.

If two objects have at least one of the configured primary_key_fields equal then they are equal. A primary key field can be any of:

string: Two objects are equal if the values at the given key paths
are equal. Example:
For ‘key1.key2’ the objects are equal if obj1[‘key1’][‘key2’] == obj2[‘key1’][‘key2’].
list: Two objects are equal if all the values at the key paths
in the list are equal. Example:
For [‘key1’, ‘key2.key3’] the objects are equal if obj1[‘key1’] == obj2[‘key1’] and obj1[‘key2’][‘key3’] == obj2[‘key2’][‘key3’].

For normalizing the fields in the objects to be compared, one can add a normalization function for each field in the normalization_functions dict.

Example

Setting the normalization_functions field to:
{'key1': str.lower}
would normalize
obj1 = {‘key1’: ‘ID123’} and obj2 = {‘key1’: ‘id123’} to obj1 = {‘key1’: ‘id123’} and obj2 = {‘key1’: ‘id123’}
Parameters:
  • l1 – First list of entities.
  • l2 – Second list of entities.

json_merger.stats

class json_merger.stats.ListMatchStats(lst, root)[source]

Class for holding list entity matching stats.

Parameters:
  • lst – The list of elements that needs to be matched.
  • root – The ancestor of the list of elements that needs to be matched.
in_result_idx

Indices of elements in lst that are present in the end result.

in_result

Elements in lst that are present in the end result.

not_in_result_idx

Indices of elements in lst that are not present in the end result.

not_in_result

Elements in lst that are not present in the end result.

not_in_result_root_match_idx

Indices of elements that are not in the end result but were matched with root elements.

not_in_result_root_match

Elements that are not in the end result but were matched with root elements.

not_in_result_not_root_match_idx

Indices of elements that are not in the end result and were not matched with any root elements.

not_in_result_not_root_match

Elements that are not in the end result and were not matched with any root elements.

not_in_result_root_match_pairs

Pairs of (lst, root) elements that are not in the end result but were matched.

add_root_match(lst_idx, root_idx)[source]

Adds a match for the elements avaialble at lst_idx and root_idx.

move_to_result(lst_idx)[source]

Moves element from lst available at lst_idx.

json_merger.errors

exception json_merger.errors.MergeError(message, content)[source]

Merging Error.

message

Error message.

content

List of conflicts that occured when merging.

json_merger.conflict

class json_merger.conflict.Conflict[source]

Immutable and Hashable representation of a conflict.

conflict_type

A json_merger.conflict.ConflictType member.

path

A tuple containing the path to the conflictual field.

body

Optional value representing the body of the conflict.

Note

Even if the conflict body can be any arbitrary object, this is saved internally as an immutable object so that a Conflict instance can be safely used in sets or as a dict key.

to_json()[source]

Deserializes conflict to a JSON object.

with_prefix(root_path)[source]

Returns a new conflict with a prepended prefix as a path.

class json_merger.conflict.ConflictType[source]

Types of Conflict.

REORDER

The list specified by the path might need to be reordered.

MANUAL_MERGE

The triple specified as the conflict body needs to be manually merged and added to the conflict path.

ADD_BACK_TO_HEAD

The object specified as the conflict body might need to be added back to the list specified in the conflict’s path.

SET_FIELD

The object specified as the conflict body needs to be added at the path specifed in the conflict object.

REMOVE_FIELD

The value or object present at the path specified in the path conflict needs to be removed.