anchor.diff:      maps:keys(DataObject);                      % lists:sort(
   keys(DataObject) -> 
       keys(decode(DataObject)).
  -
  -%% @doc Produces a new data object by calling the function fun F(K, V1) 
  -%% for every K to value V1 association in data object in arbitrary order. 
  -%% The function fun F/2 must return the value V2 to be associated with key K 
  -%% for the new data object. 
  -%% null values are ignored and not carried over to new data object.
  --spec map(fun(), data_object()) -> data_object().
  -map(Fun,DataObject) when is_list(DataObject) ->
  -    lists:map(fun({K,V}) -> {K,Fun(K,V)} end,
  -              proplists:unfold(DataObject));
  -map(Fun,DataObject) when is_map(DataObject) ->
  -    maps:map(Fun,clean_null_values(DataObject));
  -map(Fun,DataObject) ->
  -    encode(map(Fun,decode(DataObject))).
  -
  -
  -%% @doc Create new imem json data object using default type
  --spec new() -> data_object().
  -new() -> new(proplist).
  -
  -%% @doc Create new imen json data object
  --spec new(Type) -> data_object() when Type :: json | proplist | map.
  -new(proplist) -> [];
  -new(map) -> #{};
  -new(json) -> <<"{}">>.
  -
   
   %% @doc Get function, same as get(Key,DataObject,undefined)
   -spec get(key(),data_object()) -> value() | undefined.
  
positive.code: find(Key,DataObject) ->
      find(Key, decode(DataObject)).
  
  %% @doc Standard fold function, returns accumulator. null values are ignored.
  %% Fun = fun((K, V, AccIn) -> AccOut)
  -spec fold(fun(), Init, data_object()) -> Acc when Init :: term(), Acc :: term().
  fold(Fun,Init,DataObject) when is_list(DataObject) -> 
      lists:foldl(fun({K,V},Acc) -> Fun(K,V,Acc) end,
                  Init,
                  proplists:unfold(clean_null_values(DataObject)));
  fold(Fun,Init,DataObject) when is_map(DataObject) -> 
      maps:fold(Fun,Init,clean_null_values(DataObject));
  fold(Fun,Init,DataObject) -> 
      fold(Fun,Init,decode(DataObject)).
  
  
  %% @doc Check if data object has key
  -spec has_key(key(), data_object()) -> boolean().
  has_key(Key,DataObject) when is_list(DataObject) ->
      proplists:is_defined(Key,DataObject);
  has_key(Key,DataObject) when is_map(DataObject) ->
      maps:is_key(Key,DataObject);
  has_key(Key,DataObject) -> 
      has_key(Key,decode(DataObject)).
  
  %% @doc Erlang term ordered list of keys used by data object
  -spec keys(data_object()) -> list().
  keys(DataObject) when is_list(DataObject) ->
  
negative.code:     maps:to_list(DataObject);
  to_proplist(DataObject) ->
      to_proplist(decode(DataObject)).
  
  %% @doc Projects a parsed Json Path (from jpparse) on a json object
  %% and extracts matched values. nomatch is return if no match is found.
  