anchor.diff:  %% without problems.
   %% Current strategy is to use jsonx as the main parser and fall back to
   %% mochijson3 in case of parsing issues.
  --spec decode_value_jsonx(string(),
  -                         avro_type_or_name(),
  -                         fun((string()) -> avro_type()))
  -                        -> avro_value().
  -
  -decode_value_jsonx(JsonValue, Schema, ExtractTypeFun) ->
  -  case jsonx:decode(JsonValue, [{format, struct}]) of
  -    {error, _Err, _Pos} ->
  -      decode_value(JsonValue, Schema, ExtractTypeFun);
  -    Decoded ->
  -      parse_value(Decoded, Schema, ExtractTypeFun)
  -  end.
  +-spec decode_value(binary(), avro_type_or_name(),
  +                   fun((string()) -> avro_type()), options()) ->
  +                      avro_value() | term().
  +decode_value(JsonValue, Schema, ExtractTypeFun, Options) ->
  +  DecodedJson =
  +    case lists:keyfind(decoder, Options) of
  +      {_, jsonx} ->
  +        case jsonx:decode(JsonValue, [{format, struct}]) of
  +          {error, _Err, _Pos} ->
  +            mochijson3:decode(JsonValue);
  +          Decoded ->
  +            Decoded
  +        end;
  +      _ ->
  +        mochijson3:decode(JsonValue)
  +    end,
  +  IsWrapped = case lists:keyfind(is_wrapped, Options) of
  +                {is_wrapped, V} -> V;
  +                false           -> true %% parse to wrapped value by default
  +              end,
  +  parse(DecodedJson, Schema, ExtractTypeFun, IsWrapped).
  +
  +%% Decode value specified as Json string according to Avro schema
  +%% in Schema. ExtractTypeFun should be provided to retrieve types
  +%% specified by their names inside Schema.
  +-spec decode_value(binary(),
  +                   avro_type_or_name(),
  +                   fun((string()) -> avro_type()))
  +                  -> avro_value().
  +decode_value(JsonValue, Schema, ExtractTypeFun) ->
  +  decode_value(JsonValue, Schema, ExtractTypeFun, [{decoder, mochijson3}]).
   
   %%%===================================================================
   %%% Schema parsing
  
positive.code: %%% Values parsing
  %%%===================================================================
  
  parse_value(null, Type, _ExtractFun) when ?AVRO_IS_NULL_TYPE(Type) ->
    avro_primitive:null();
  
  parse_value(V, Type, _ExtractFun) when ?AVRO_IS_BOOLEAN_TYPE(Type) andalso
                                         is_boolean(V) ->
    avro_primitive:boolean(V);
  
  parse_value(V, Type, _ExtractFun) when ?AVRO_IS_INT_TYPE(Type) andalso
                                         is_integer(V)           andalso
                                         V >= ?INT4_MIN          andalso
                                         V =< ?INT4_MAX ->
    avro_primitive:int(V);
  
  parse_value(V, Type, _ExtractFun) when ?AVRO_IS_LONG_TYPE(Type) andalso
                                         is_integer(V)            andalso
                                         V >= ?INT8_MIN           andalso
                                         V =< ?INT8_MAX ->
    avro_primitive:long(V);
  
  parse_value(V, Type, _ExtractFun) when ?AVRO_IS_FLOAT_TYPE(Type) andalso
                                         (is_float(V) orelse is_integer(V)) ->
    avro_primitive:float(V);
  
  parse_value(V, Type, _ExtractFun) when ?AVRO_IS_DOUBLE_TYPE(Type) andalso
                                         (is_float(V) orelse is_integer(V)) ->
    avro_primitive:double(V);
  
  parse_value(V, Type, _ExtractFun) when ?AVRO_IS_BYTES_TYPE(Type) andalso
                                         is_binary(V) ->
    Bin = parse_bytes(V),
    avro_primitive:bytes(Bin);
  
  parse_value(V, Type, _ExtractFun) when ?AVRO_IS_STRING_TYPE(Type) andalso
                                         is_binary(V) ->
    avro_primitive:string(binary_to_list(V));
  
  parse_value(V, Type, ExtractFun) when ?AVRO_IS_RECORD_TYPE(Type) ->
    parse_record(V, Type, ExtractFun);
  
  parse_value(V, Type, _ExtractFun) when ?AVRO_IS_ENUM_TYPE(Type)
                                    andalso is_binary(V) ->
    avro_enum:new(Type, binary_to_list(V));
  
  parse_value(V, Type, ExtractFun) when ?AVRO_IS_ARRAY_TYPE(Type) ->
    parse_array(V, Type, ExtractFun);
  
  parse_value(V, Type, ExtractFun) when ?AVRO_IS_MAP_TYPE(Type) ->
    parse_map(V, Type, ExtractFun);
  
  parse_value(V, Type, ExtractFun) when ?AVRO_IS_UNION_TYPE(Type) ->
    parse_union(V, Type, ExtractFun);
  
  parse_value(V, Type, ExtractFun) when ?AVRO_IS_FIXED_TYPE(Type) ->
    parse_fixed(V, Type, ExtractFun);
  
  parse_value(Value, SchemaName, ExtractFun) when is_list(SchemaName) ->
    %% Type is defined by its name
    Schema = ExtractFun(SchemaName),
    parse_value(Value, Schema, ExtractFun);
  
  parse_value(_Value, _Schema, _ExtractFun) ->
    erlang:error(value_does_not_correspond_to_schema).
  
  parse_bytes(BytesStr) ->
    list_to_binary(parse_bytes(BytesStr, [])).
  
negative.code: -export([ decode_schema/1
          , decode_schema/2
          , decode_value/3
          , decode_value/4
          ]).
  
  -include("erlavro.hrl").
  
  -type options() :: [{atom(), term()}].
  
  %%%===================================================================
  %%% API
  