diff --git a/jdiff/__init__.py b/jdiff/__init__.py
index 3d0a62b..37e2b6b 100644
--- a/jdiff/__init__.py
+++ b/jdiff/__init__.py
@@ -1,4 +1,5 @@
 """Pre/Post Check library."""
+
 from .check_types import CheckType
 from .extract_data import extract_data_from_json
 
diff --git a/jdiff/check_types.py b/jdiff/check_types.py
index 8b1bd0d..a58f70f 100644
--- a/jdiff/check_types.py
+++ b/jdiff/check_types.py
@@ -1,4 +1,5 @@
 """CheckType Implementation."""
+
 from typing import List, Tuple, Dict, Any, Union
 from abc import ABC, abstractmethod
 from .evaluators import diff_generator, parameter_evaluator, regex_evaluator, operator_evaluator
diff --git a/jdiff/evaluators.py b/jdiff/evaluators.py
index 6b9474a..eac23e6 100644
--- a/jdiff/evaluators.py
+++ b/jdiff/evaluators.py
@@ -1,4 +1,5 @@
 """Evaluators."""
+
 import re
 from typing import Any, Mapping, Dict, Tuple, List
 from deepdiff import DeepDiff
diff --git a/jdiff/extract_data.py b/jdiff/extract_data.py
index a4a57d0..9190401 100644
--- a/jdiff/extract_data.py
+++ b/jdiff/extract_data.py
@@ -1,13 +1,16 @@
 """Extract data from JSON. Based on custom JMSPath implementation."""
+
 import re
 import warnings
-from typing import Mapping, List, Dict, Any, Union, Optional
+from typing import Any, Dict, List, Mapping, Optional, Union
+
 import jmespath
+
 from .utils.data_normalization import exclude_filter, flatten_list
 from .utils.jmespath_parsers import (
-    jmespath_value_parser,
-    jmespath_refkey_parser,
     associate_key_of_my_value,
+    jmespath_refkey_parser,
+    jmespath_value_parser,
     keys_values_zipper,
     multi_reference_keys,
 )
@@ -48,7 +51,10 @@ def extract_data_from_json(data: Union[Mapping, List], path: str = "*", exclude:
     if len(re.findall(r"\$.*?\$", path)) > 1:
         clean_path = path.replace("$", "")
         values = jmespath.search(f"{clean_path}{' | []' * (path.count('*') - 1)}", data)
-        return keys_values_zipper(multi_reference_keys(path, data), associate_key_of_my_value(clean_path, values))
+        return keys_values_zipper(
+            multi_reference_keys(path, data),
+            associate_key_of_my_value(clean_path, values),
+        )
 
     values = jmespath.search(jmespath_value_parser(path), data)
 
diff --git a/jdiff/operator.py b/jdiff/operator.py
index 6c07000..ffa3921 100644
--- a/jdiff/operator.py
+++ b/jdiff/operator.py
@@ -1,4 +1,5 @@
 """Operator diff."""
+
 import operator
 from typing import Any, List, Tuple
 
diff --git a/jdiff/utils/data_normalization.py b/jdiff/utils/data_normalization.py
index 8a5e053..d658fa3 100644
--- a/jdiff/utils/data_normalization.py
+++ b/jdiff/utils/data_normalization.py
@@ -1,4 +1,5 @@
 """Data Normalization utilities."""
+
 from typing import List, Generator, Union, Dict
 
 
diff --git a/jdiff/utils/diff_helpers.py b/jdiff/utils/diff_helpers.py
index a22c4a6..60f190f 100644
--- a/jdiff/utils/diff_helpers.py
+++ b/jdiff/utils/diff_helpers.py
@@ -1,8 +1,10 @@
 """Diff helpers."""
+
 import re
 from collections import defaultdict
-from functools import partial
-from typing import Mapping, Dict, List, DefaultDict
+from functools import partial, reduce
+from operator import getitem
+from typing import DefaultDict, Dict, List, Mapping
 
 REGEX_PATTERN_RELEVANT_KEYS = r"'([A-Za-z0-9_\./\\-]*)'"
 
@@ -62,8 +64,12 @@ def fix_deepdiff_key_names(obj: Mapping) -> Dict:
     result = {}  # type: Dict
     for key, value in obj.items():
         key_parts = re.findall(REGEX_PATTERN_RELEVANT_KEYS, key)
-        if not key_parts:  # If key parts can't be find, keep original key so data is not lost.
-            key_parts = [key.replace("root", "index_element")]  # replace root from DeepDiff with more meaningful name.
+        if (
+            not key_parts
+        ):  # If key parts can't be find, keep original key so data is not lost.
+            key_parts = [
+                key.replace("root", "index_element")
+            ]  # replace root from DeepDiff with more meaningful name.
         partial_res = group_value(key_parts, value)
         dict_merger(result, partial_res)
     return result
@@ -79,9 +85,97 @@ def group_value(tree_list: List, value: Dict) -> Dict:
 def dict_merger(original_dict: Dict, dict_to_merge: Dict):
     """Function to merge a dictionary (dict_to_merge) recursively into the original_dict."""
     for key in dict_to_merge.keys():
-        if key in original_dict and isinstance(original_dict[key], dict) and isinstance(dict_to_merge[key], dict):
+        if (
+            key in original_dict
+            and isinstance(original_dict[key], dict)
+            and isinstance(dict_to_merge[key], dict)
+        ):
             dict_merger(original_dict[key], dict_to_merge[key])
         elif key in original_dict.keys():
-            original_dict[key + "_dup!"] = dict_to_merge[key]  # avoid overwriting existing keys.
+            original_dict[key + "_dup!"] = dict_to_merge[
+                key
+            ]  # avoid overwriting existing keys.
         else:
             original_dict[key] = dict_to_merge[key]
+
+
+def _parse_index_element_string(index_element_string):
+    """Build out dictionary from the index element string."""
+    result = {}
+    pattern = r"\[\'(.*?)\'\]"
+    match = re.findall(pattern, index_element_string)
+    if match:
+        for inner_key in match[1::]:
+            result[inner_key] = ""
+    return match, result
+
+
+def set_nested_value(data, keys, value):
+    """
+    Recursively sets a value in a nested dictionary, given a list of keys.
+
+    Args:
+        data (dict): The nested dictionary to modify.
+        keys (list): A list of keys to access the target value.
+        value: The value to set.
+
+    Returns:
+        None: The function modifies the dictionary in place.  Returns None.
+    """
+    if not keys:
+        return  # Should not happen, but good to have.
+    if len(keys) == 1:
+        data[keys[0]] = value
+    else:
+        if keys[0] not in data:
+            data[keys[0]] = {}  # Create the nested dictionary if it doesn't exist
+        set_nested_value(data[keys[0]], keys[1:], value)
+
+
+def parse_diff(jdiff_evaluate_response, actual, intended, match_config):
+    """Parse jdiff evaluate result into missing and extra dictionaries."""
+    extra = {}
+    missing = {}
+
+    def process_diff(_map, extra_map, missing_map, previous_key=None):
+        for key, value in _map.items():
+            if (
+                isinstance(value, dict)
+                and "new_value" in value
+                and "old_value" in value
+            ):
+                extra_map[key] = value["old_value"]
+                missing_map[key] = value["new_value"]
+            elif isinstance(value, str):
+                if "missing" in value:
+                    extra_map[key] = actual.get(match_config, {}).get(key)
+                if "new" in value:
+                    key_chain, _ = _parse_index_element_string(key)
+                    new_value = reduce(getitem, key_chain, intended)
+                    set_nested_value(missing_map, key_chain[1::], new_value)
+            elif isinstance(value, defaultdict):
+                if dict(value).get("new"):
+                    missing[previous_key][key] = dict(value).get("new", {})
+                if dict(value).get("missing"):
+                    extra_map[previous_key][key] = dict(value).get("missing", {})
+            elif isinstance(value, dict):
+                extra_map[key] = {}
+                missing_map[key] = {}
+                process_diff(value, extra_map[key], missing_map[key], previous_key=key)
+        return extra_map, missing_map
+
+    extras, missing = process_diff(jdiff_evaluate_response, extra, missing)
+    # Don't like this, but with less the performant way of doing it right now it works to clear out
+    # Any empty dicts that are left over from the diff.
+    # This is a bit of a hack, but it works for now.
+    final_extras = extras.copy()
+    final_missing = missing.copy()
+    for key, value in extras.items():
+        if isinstance(value, dict):
+            if not value:
+                del final_extras[key]
+    for key, value in missing.items():
+        if isinstance(value, dict):
+            if not value:
+                del final_missing[key]
+    return final_extras, final_missing
diff --git a/jdiff/utils/jmespath_parsers.py b/jdiff/utils/jmespath_parsers.py
index ee1e669..b35b839 100644
--- a/jdiff/utils/jmespath_parsers.py
+++ b/jdiff/utils/jmespath_parsers.py
@@ -5,6 +5,7 @@
 From one expression defined in jdiff, we will derive two expressions: one expression that traverse the json output and get the
 evaluated bit of it, the second will target the reference key relative to the value to evaluate. More on README.md
 """
+
 import re
 from typing import Mapping, List, Union
 
diff --git a/tasks.py b/tasks.py
index 18508fe..4dfecfe 100644
--- a/tasks.py
+++ b/tasks.py
@@ -1,4 +1,5 @@
 """Tasks for use with Invoke."""
+
 import os
 import sys
 from invoke import task
diff --git a/tests/test_diff_generator.py b/tests/test_diff_generator.py
index 9c0892d..a9c3412 100644
--- a/tests/test_diff_generator.py
+++ b/tests/test_diff_generator.py
@@ -1,4 +1,5 @@
 """Diff generator tests."""
+
 import pytest
 from jdiff.evaluators import diff_generator
 from jdiff import extract_data_from_json
diff --git a/tests/test_diff_helpers.py b/tests/test_diff_helpers.py
index 82a23fa..fe8c045 100644
--- a/tests/test_diff_helpers.py
+++ b/tests/test_diff_helpers.py
@@ -1,5 +1,17 @@
 """DIff helpers unit tests."""
-from jdiff.utils.diff_helpers import dict_merger, group_value, fix_deepdiff_key_names, get_diff_iterables_items
+
+from collections import defaultdict
+
+import pytest
+
+from jdiff.utils.diff_helpers import (
+    _parse_index_element_string,
+    dict_merger,
+    fix_deepdiff_key_names,
+    get_diff_iterables_items,
+    group_value,
+    parse_diff,
+)
 
 
 def test_dict_merger():
@@ -37,10 +49,172 @@ def test_get_diff_iterables_items():
     diff_result = {
         "values_changed": {"root['Ethernet1'][0]['port']": {"new_value": "518", "old_value": "519"}},
         "iterable_item_added": {
-            "root['Ethernet3'][1]": {"hostname": "ios-xrv-unittest", "port": "Gi0/0/0/0"},
+            "root['Ethernet3'][1]": {
+                "hostname": "ios-xrv-unittest",
+                "port": "Gi0/0/0/0",
+            },
         },
     }
     result = get_diff_iterables_items(diff_result)
 
     assert list(dict(result).keys())[0] == "['Ethernet3']"
     assert list(list(dict(result).values())[0].values())[0] == [{"hostname": "ios-xrv-unittest", "port": "Gi0/0/0/0"}]
+
+
+index_element_case_1 = (
+    "index_element['foo']['ip name']",
+    {"ip name": ""},
+)
+
+index_element_case_2 = (
+    "index_element['foo']['ip name']['ip domain']",
+    {"ip name": "", "ip domain": ""},
+)
+
+
+index_element_tests = [index_element_case_1, index_element_case_2]
+
+
+@pytest.mark.parametrize("index_element, result", index_element_tests)
+def test__parse_index_element_string(index_element, result):
+    """Test that index_element can be unpacked."""
+    _, parsed_result = _parse_index_element_string(index_element)
+    assert parsed_result == result
+
+
+parse_diff_case_1 = (
+    {
+        "hostname": {"new_value": "veos", "old_value": "veos-0"},
+        "domain-name": "missing",
+    },
+    {"openconfig-system:config": {"domain-name": "ntc.com", "hostname": "veos-0"}},
+    {"openconfig-system:config": {"hostname": "veos"}},
+    "openconfig-system:config",
+    {"hostname": "veos-0", "domain-name": "ntc.com"},
+    {"hostname": "veos"},
+)
+
+parse_diff_case_2 = (
+    {
+        "hostname": {"new_value": "veos", "old_value": "veos-0"},
+        "domain-name": "missing",
+        "index_element['openconfig-system:config']['ip name']": "new",
+    },
+    {"openconfig-system:config": {"domain-name": "ntc.com", "hostname": "veos-0"}},
+    {"openconfig-system:config": {"hostname": "veos", "ip name": "ntc.com"}},
+    "openconfig-system:config",
+    {"domain-name": "ntc.com", "hostname": "veos-0"},
+    {"hostname": "veos", "ip name": "ntc.com"},
+)
+
+parse_diff_case_3 = (
+    {
+        "domain-name": "missing",
+        "hostname": "missing",
+        "index_element['openconfig-system:config']['ip name']": "new",
+    },
+    {"openconfig-system:config": {"domain-name": "ntc.com", "hostname": "veos-0"}},
+    {"openconfig-system:config": {"ip name": "ntc.com"}},
+    "openconfig-system:config",
+    {"domain-name": "ntc.com", "hostname": "veos-0"},
+    {"ip name": "ntc.com"},
+)
+
+parse_diff_case_4 = (
+    {"domain-name": "missing"},
+    {"openconfig-system:config": {"domain-name": "ntc.com", "hostname": "veos"}},
+    {"openconfig-system:config": {"hostname": "veos"}},
+    "openconfig-system:config",
+    {"domain-name": "ntc.com"},
+    {},
+)
+
+parse_diff_case_5 = (
+    {
+        "hostname": {"new_value": "veos", "old_value": "veos-0"},
+        "domain-name": "missing",
+        "index_element['openconfig-system:config']['ip name']": "new",
+    },
+    {"openconfig-system:config": {"domain-name": "ntc.com", "hostname": "veos-0"}},
+    {"openconfig-system:config": {"hostname": "veos", "ip name": "ntc.com"}},
+    "openconfig-system:config",
+    {"hostname": "veos-0", "domain-name": "ntc.com"},
+    {"ip name": "ntc.com", "hostname": "veos"},
+)
+
+parse_diff_case_6 = (
+    {
+        "servers": {
+            "server": defaultdict(
+                list,
+                {
+                    "new": [
+                        {
+                            "address": "1.us.pool.ntp.org",
+                            "config": {"address": "1.us.pool.ntp.org"},
+                            "state": {"address": "1.us.pool.ntp.org"},
+                        }
+                    ]
+                },
+            )
+        }
+    },
+    {"openconfig-system:ntp": {"servers": {"server": []}}},
+    {
+        "openconfig-system:ntp": {
+            "servers": {
+                "server": [
+                    {
+                        "address": "1.us.pool.ntp.org",
+                        "config": {"address": "1.us.pool.ntp.org"},
+                        "state": {"address": "1.us.pool.ntp.org"},
+                    }
+                ]
+            }
+        }
+    },
+    "openconfig-system:ntp",
+    {},
+    {
+        "servers": {
+            "server": [
+                {
+                    "address": "1.us.pool.ntp.org",
+                    "config": {
+                        "address": "1.us.pool.ntp.org",
+                    },
+                    "state": {
+                        "address": "1.us.pool.ntp.org",
+                    },
+                },
+            ],
+        },
+    },
+)
+
+parse_diff_tests = [
+    parse_diff_case_1,
+    parse_diff_case_2,
+    parse_diff_case_3,
+    parse_diff_case_4,
+    parse_diff_case_5,
+    parse_diff_case_6,
+]
+
+
+@pytest.mark.parametrize(
+    "jdiff_evaluate_response, actual, intended, match_config, extra, missing",
+    parse_diff_tests,
+)
+def test_parse_diff(
+    jdiff_evaluate_response, actual, intended, match_config, extra, missing
+):  # pylint: disable=too-many-arguments
+    """Test that index_element can be unpacked."""
+    parsed_extra, parsed_missing = parse_diff(
+        jdiff_evaluate_response,
+        actual,
+        intended,
+        match_config,
+    )
+    assert parsed_extra == extra
+    assert parsed_missing == missing
diff --git a/tests/test_get_value.py b/tests/test_get_value.py
index e437c55..55f187d 100644
--- a/tests/test_get_value.py
+++ b/tests/test_get_value.py
@@ -1,4 +1,5 @@
 """Test extract_data_from_json."""
+
 import pytest
 from jdiff import extract_data_from_json
 from .utility import load_json_file, ASSERT_FAIL_MESSAGE
diff --git a/tests/test_jmespath_parsers.py b/tests/test_jmespath_parsers.py
index 972acc1..c0f6a9a 100644
--- a/tests/test_jmespath_parsers.py
+++ b/tests/test_jmespath_parsers.py
@@ -1,4 +1,5 @@
 """jmespath parser unit tests."""
+
 import pytest
 from jdiff.utils.jmespath_parsers import (
     jmespath_value_parser,
diff --git a/tests/test_operators.py b/tests/test_operators.py
index 3d5fd1f..6748752 100644
--- a/tests/test_operators.py
+++ b/tests/test_operators.py
@@ -1,4 +1,5 @@
 """Unit tests for operator check-type."""
+
 import pytest
 from jdiff import CheckType, extract_data_from_json
 from .utility import load_json_file, ASSERT_FAIL_MESSAGE
diff --git a/tests/test_sw_upgrade_device_state.py b/tests/test_sw_upgrade_device_state.py
index 05c34b8..498c175 100644
--- a/tests/test_sw_upgrade_device_state.py
+++ b/tests/test_sw_upgrade_device_state.py
@@ -1,4 +1,5 @@
 """Tests for typical software upgrade device state check."""
+
 from copy import deepcopy
 import pytest
 from jdiff import CheckType, extract_data_from_json
diff --git a/tests/test_type_checks.py b/tests/test_type_checks.py
index 7345cde..17d9269 100644
--- a/tests/test_type_checks.py
+++ b/tests/test_type_checks.py
@@ -1,4 +1,5 @@
 """Check Type unit tests."""
+
 import pytest
 from jdiff.check_types import (
     CheckType,
diff --git a/tests/test_validates.py b/tests/test_validates.py
index c10a8ff..7ece4ce 100644
--- a/tests/test_validates.py
+++ b/tests/test_validates.py
@@ -1,4 +1,5 @@
 """Unit tests for validator CheckType method."""
+
 import pytest
 from jdiff import CheckType
 
