anchor.diff:              json_to_erlang(Tail, Parsers, Zone#partial_zone{sha = Value});
           {<<"records">>, Value} ->
               Records = lists:map(
  -                   fun(JsonRecord) ->
  -                       Data = json_record_to_list(JsonRecord),
  -                       %% Filter by context
  -                       case apply_context_options(Data) of
  -                           pass ->
  -                               case json_record_to_erlang(Data) of
  -                                   {} -> try_custom_parsers(Data, Parsers);
  -                                   ParsedRecord -> ParsedRecord
  -                               end;
  -                           _ ->
  -                               {}
  -                           end
  -                   end, Value),
  +                        fun(JsonRecord) ->
  +                                Data = json_record_to_list(JsonRecord),
  +                                %% Filter by context
  +                                case apply_context_options(Data) of
  +                                    pass ->
  +                                        case json_record_to_erlang(Data) of
  +                                            {} -> try_custom_parsers(Data, Parsers);
  +                                            ParsedRecord -> ParsedRecord
  +                                        end;
  +                                    _ ->
  +                                        {}
  +                                end
  +                        end, Value),
               FilteredRecords = lists:filter(record_filter(), Records),
               DistinctRecords = lists:usort(FilteredRecords),
               json_to_erlang(Tail, Parsers, Zone#partial_zone{records = DistinctRecords})
       end.
   
   record_filter() ->
  -  fun(R) ->
  -      case R of
  -        {} -> false;
  -        _ -> true
  -      end
  -  end.
  +    fun(R) ->
  +            case R of
  +                {} -> false;
  +                _ -> true
  +            end
  +    end.
   
   -spec apply_context_list_check(edns_set(), edns_set()) -> [fail] | [pass].
   apply_context_list_check(ContextAllowSet, ContextSet) ->
  -  case sets:size(sets:intersection(ContextAllowSet, ContextSet)) of
  -    0 -> [fail];
  -    _ -> [pass]
  -  end.
  +    case sets:size(sets:intersection(ContextAllowSet, ContextSet)) of
  +        0 -> [fail];
  +        _ -> [pass]
  +    end.
   
   -spec apply_context_match_empty_check(boolean(), [any()]) -> [fail] | [pass].
   apply_context_match_empty_check(true, []) -> [pass];
  
positive.code:     ip_binaries_to_tuples(T, [Addr | Acc]).
  
  json_record_to_erlang([Name, Type, _Ttl, null, _]) ->
    erldns_log:error("record name=~p type=~p has null data", [Name, Type]),
    {};
  
  json_record_to_erlang([Name, <<"SOA">>, Ttl, Data, _Context]) ->
    #dns_rr{
       name = Name,
       type = ?DNS_TYPE_SOA,
       data = #dns_rrdata_soa{
                 mname = proplists:get_value(<<"mname">>, Data),
                 rname = proplists:get_value(<<"rname">>, Data),
                 serial = proplists:get_value(<<"serial">>, Data),
                 refresh = proplists:get_value(<<"refresh">>, Data),
                 retry = proplists:get_value(<<"retry">>, Data),
                 expire = proplists:get_value(<<"expire">>, Data),
                 minimum = proplists:get_value(<<"minimum">>, Data)
                },
       ttl = Ttl};
  
  json_record_to_erlang([Name, <<"NS">>, Ttl, Data, _Context]) ->
    #dns_rr{
       name = Name,
       type = ?DNS_TYPE_NS,
       data = #dns_rrdata_ns{
                 dname = proplists:get_value(<<"dname">>, Data)
                },
       ttl = Ttl};
  
  json_record_to_erlang([Name, <<"A">>, Ttl, Data, _Context]) ->
    Ip = proplists:get_value(<<"ip">>, Data),
    case inet_parse:address(binary_to_list(Ip)) of
      {ok, Address} ->
        #dns_rr{name = Name, type = ?DNS_TYPE_A, data = #dns_rrdata_a{ip = Address}, ttl = Ttl};
      {error, Reason} ->
        erldns_log:error("Failed to parse A record address ~p: ~p", [Ip, Reason]),
        {}
    end;
  
  json_record_to_erlang([Name, <<"AAAA">>, Ttl, Data, _Context]) ->
    Ip = proplists:get_value(<<"ip">>, Data),
    case inet_parse:address(binary_to_list(Ip)) of
      {ok, Address} ->
        #dns_rr{name = Name, type = ?DNS_TYPE_AAAA, data = #dns_rrdata_aaaa{ip = Address}, ttl = Ttl};
      {error, Reason} ->
        erldns_log:error("Failed to parse AAAA record address ~p: ~p", [Ip, Reason]),
        {}
    end;
  
  json_record_to_erlang([Name, <<"CNAME">>, Ttl, Data, _Context]) ->
    #dns_rr{
       name = Name,
       type = ?DNS_TYPE_CNAME,
       data = #dns_rrdata_cname{dname = proplists:get_value(<<"dname">>, Data)},
       ttl = Ttl};
  
  json_record_to_erlang([Name, <<"MX">>, Ttl, Data, _Context]) ->
    #dns_rr{
       name = Name,
       type = ?DNS_TYPE_MX,
       data = #dns_rrdata_mx{
                 exchange = proplists:get_value(<<"exchange">>, Data),
                 preference = proplists:get_value(<<"preference">>, Data)
                },
       ttl = Ttl};
  
  json_record_to_erlang([Name, <<"HINFO">>, Ttl, Data, _Context]) ->
    #dns_rr{
       name = Name,
       type = ?DNS_TYPE_HINFO,
       data = #dns_rrdata_hinfo{
                 cpu = proplists:get_value(<<"cpu">>, Data),
                 os = proplists:get_value(<<"os">>, Data)
                },
       ttl = Ttl};
  
  json_record_to_erlang([Name, <<"RP">>, Ttl, Data, _Context]) ->
    #dns_rr{
       name = Name,
       type = ?DNS_TYPE_RP,
       data = #dns_rrdata_rp{
                 mbox = proplists:get_value(<<"mbox">>, Data),
                 txt = proplists:get_value(<<"txt">>, Data)
                },
       ttl = Ttl};
  
  json_record_to_erlang([Name, <<"TXT">>, Ttl, Data, _Context]) ->
    %% This function call may crash. Handle it as a bad record.
    try erldns_txt:parse(proplists:get_value(<<"txt">>, Data)) of
      ParsedText ->
        #dns_rr{
           name = Name,
           type = ?DNS_TYPE_TXT,
           data = #dns_rrdata_txt{txt = lists:flatten(ParsedText)},
           ttl = Ttl}
    catch
      Exception:Reason ->
        erldns_log:error("Error parsing TXT ~p: ~p (~p: ~p)", [Name, Data, Exception, Reason])
    end;
  
  
  json_record_to_erlang([Name, <<"SPF">>, Ttl, Data, _Context]) ->
    #dns_rr{
       name = Name,
       type = ?DNS_TYPE_SPF,
       data = #dns_rrdata_spf{spf = [proplists:get_value(<<"spf">>, Data)]},
       ttl = Ttl};
  
  json_record_to_erlang([Name, <<"PTR">>, Ttl, Data, _Context]) ->
    #dns_rr{
       name = Name,
       type = ?DNS_TYPE_PTR,
       data = #dns_rrdata_ptr{dname = proplists:get_value(<<"dname">>, Data)},
       ttl = Ttl};
  
  json_record_to_erlang([Name, <<"SSHFP">>, Ttl, Data, _Context]) ->
    %% This function call may crash. Handle it as a bad record.
    try hex_to_bin(proplists:get_value(<<"fp">>, Data)) of
      Fp ->
        #dns_rr{
           name = Name,
           type = ?DNS_TYPE_SSHFP,
           data = #dns_rrdata_sshfp{
                     alg = proplists:get_value(<<"alg">>, Data),
                     fp_type = proplists:get_value(<<"fptype">>, Data),
                     fp = Fp
                    },
           ttl = Ttl}
    catch
      Exception:Reason ->
        erldns_log:error("Error parsing SSHFP ~p: ~p (~p: ~p)", [Name, Data, Exception, Reason]),
        {}
    end;
  
  json_record_to_erlang([Name, <<"SRV">>, Ttl, Data, _Context]) ->
    #dns_rr{
       name = Name,
       type = ?DNS_TYPE_SRV,
       data = #dns_rrdata_srv{
                 priority = proplists:get_value(<<"priority">>, Data),
                 weight = proplists:get_value(<<"weight">>, Data),
                 port = proplists:get_value(<<"port">>, Data),
                 target = proplists:get_value(<<"target">>, Data)
                },
       ttl = Ttl};
  
  json_record_to_erlang([Name, <<"NAPTR">>, Ttl, Data, _Context]) ->
    #dns_rr{
       name = Name,
       type = ?DNS_TYPE_NAPTR,
       data = #dns_rrdata_naptr{
                 order = proplists:get_value(<<"order">>, Data),
                 preference = proplists:get_value(<<"preference">>, Data),
                 flags = proplists:get_value(<<"flags">>, Data),
                 services = proplists:get_value(<<"services">>, Data),
                 regexp = proplists:get_value(<<"regexp">>, Data),
                 replacement = proplists:get_value(<<"replacement">>, Data)
                },
       ttl = Ttl};
  
  json_record_to_erlang(_Data) ->
    %erldns_log:debug("Cannot convert ~p", [Data]),
    {}.
  
  hex_to_bin(Bin) when is_binary(Bin) ->
    Fun = fun(A, B) ->
              case io_lib:fread("~16u", [A, B]) of
                {ok, [V], []} -> V;
                _ -> error(badarg)
              end
          end,
    << <<(Fun(A,B))>> || <<A, B>> <= Bin >>.
  
negative.code: -spec apply_context_options([any()]) -> pass | fail.
  apply_context_options([_, _, _, _, undefined]) -> pass;
  apply_context_options([_, _, _, _, Context]) ->
      case application:get_env(erldns, context_options) of
          {ok, ContextOptions} ->
              ContextSet = sets:from_list(Context),
              Result = lists:append([
                                     apply_context_match_empty_check(
                                       proplists:get_value(match_empty, ContextOptions), Context),
                                     apply_context_list_check(
                                       sets:from_list(proplists:get_value(allow, ContextOptions)), ContextSet)
                                    ]),
              case lists:any(fun(I) -> I =:= pass end, Result) of
                  true -> pass;
                  _ -> fail
              end;
          _ ->
              pass
      end.
  
  json_record_to_list(JsonRecord) ->
      [
       proplists:get_value(<<"name">>, JsonRecord),
       proplists:get_value(<<"type">>, JsonRecord),
       proplists:get_value(<<"ttl">>, JsonRecord),
       proplists:get_value(<<"data">>, JsonRecord),
       proplists:get_value(<<"context">>, JsonRecord)
      ].
  
  try_custom_parsers([_Name, _Type, _Ttl, _Rdata, _Context], []) ->
      {};
  try_custom_parsers(Data, [Parser|Rest]) ->
      case Parser:json_record_to_erlang(Data) of
          {} -> try_custom_parsers(Data, Rest);
          Record -> Record
      end.
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %% Internal converters
  