Просмотр исходного кода

Merge branch 'master' into hipe

Conflicts:
	src/jsone_encode.erl
Takeru Ohta 11 лет назад
Родитель
Сommit
1cddc7edbc
4 измененных файлов с 89 добавлено и 115 удалено
  1. 2 2
      rebar.config
  2. 17 19
      src/jsone_decode.erl
  3. 46 70
      src/jsone_encode.erl
  4. 24 24
      test/jsone_decode_tests.erl

+ 2 - 2
rebar.config

@@ -3,9 +3,9 @@
             warnings_as_errors,
             warn_export_all,
             warn_untyped_record,
-            inline,
             native,
-            {hipe, [o3]}
+            {hipe, [o3]},
+            inline
            ]}. 
 
 {xref_checks, [

+ 17 - 19
src/jsone_decode.erl

@@ -35,8 +35,6 @@
 %%--------------------------------------------------------------------------------
 %% Macros & Types
 %%--------------------------------------------------------------------------------
--define(ERROR(Json), error({invalid_json, Json})).
-
 -type next() :: {array_next, [jsone:json_value()]}
               | {object_value, jsone:json_object_members()}
               | {object_next, jsone:json_string(), jsone:json_object_members()}.
@@ -84,7 +82,7 @@ whitespace(<<Bin/binary>>,      Next, Nexts, Buf) ->
         object -> object(Bin, Nexts, Buf);
         string -> case Bin of
                       <<$", Bin2/binary>> -> string(Bin2, byte_size(Buf), Nexts, Buf);
-                      _                   -> ?ERROR(Bin)
+                      _                   -> error(badarg, [Bin, Next, Nexts, Buf])
                   end;
         {array_next, Values}               -> array_next(Bin, Values, Nexts, Buf);
         {object_value, Key, Members}       -> object_value(Bin, Key, Members, Nexts, Buf);
@@ -107,7 +105,7 @@ array(<<Bin/binary>>, Nexts, Buf)     -> whitespace(Bin, value, [{array_next, []
 -spec array_next(binary(), [jsone:json_value()], [next()], binary()) -> {jsone:json_value(), Rest::binary()}.
 array_next(<<$], Bin/binary>>, Values, Nexts, Buf) -> next(Bin, lists:reverse(Values), Nexts, Buf);
 array_next(<<$,, Bin/binary>>, Values, Nexts, Buf) -> whitespace(Bin, value, [{array_next, Values} | Nexts], Buf);
-array_next(<<Bin/binary>>, _Values, _Nexts, _Buf)  -> ?ERROR(Bin).
+array_next(Bin,                Values, Nexts, Buf) -> error(badarg, [Bin, Values, Nexts, Buf]).
 
 -spec object(binary(), [next()], binary()) -> {jsone:json_value(), Rest::binary()}.
 object(<<$}, Bin/binary>>, Nexts, Buf) -> next(Bin, {object, []}, Nexts, Buf);
@@ -115,12 +113,12 @@ object(<<Bin/binary>>, Nexts, Buf) -> whitespace(Bin, string, [{object_value, []
 
 -spec object_value(binary(), jsone:json_string(), jsone:json_object_members(), [next()], binary()) -> {jsone:json_value(), Rest::binary()}.
 object_value(<<$:, Bin/binary>>, Key, Members, Nexts, Buf) -> whitespace(Bin, value, [{object_next, Key, Members} | Nexts], Buf);
-object_value(<<Bin/binary>>, _Key, _Members, _Nexts, _Buf) -> ?ERROR(Bin).
+object_value(Bin,                Key, Members, Nexts, Buf) -> error(badarg, [Bin, Key, Members, Nexts, Buf]).
 
 -spec object_next(binary(), jsone:json_object_members(), [next()], binary()) -> {jsone:json_value(), Rest::binary()}.
-object_next(<<$}, Bin/binary>>, Members, Nexts, Buf) -> next(Bin, {object, lists:reverse(Members)}, Nexts, Buf);
+object_next(<<$}, Bin/binary>>, Members, Nexts, Buf) -> next(Bin, {object, Members}, Nexts, Buf);
 object_next(<<$,, Bin/binary>>, Members, Nexts, Buf) -> whitespace(Bin, string, [{object_value, Members} | Nexts], Buf);
-object_next(<<Bin/binary>>, _Members, _Nexts, _Buf)  -> ?ERROR(Bin).
+object_next(Bin,                Members, Nexts, Buf) -> error(badarg, [Bin, Members, Nexts, Buf]).
 
 -spec string(binary(), non_neg_integer(), [next()], binary()) -> {jsone:json_value(), Rest::binary()}.
 string(<<$", Bin/binary>>, Start, Nexts, Buf) -> next(Bin, binary:part(Buf, Start, byte_size(Buf) - Start), Nexts, Buf);
@@ -135,7 +133,7 @@ string(<<$\\, B/binary>>,  Start, Nexts, Buf) ->
         <<$r, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, $\r>>);
         <<$t, Bin/binary>> -> string(Bin, Start, Nexts, <<Buf/binary, $\t>>);
         <<$u, Bin/binary>> -> unicode_string(Bin, Start, Nexts, Buf);
-        _                  -> ?ERROR(B)
+        _                  -> error(badarg, [<<$\\, B/binary>>, Start, Nexts, Buf])
     end;
 string(<<C, Bin/binary>>, Start, Nexts, Buf) when 16#20 =< C ->
     string(Bin, Start, Nexts, <<Buf/binary, C>>).
@@ -151,17 +149,17 @@ unicode_string(<<N:4/binary, Bin/binary>>, Start, Nexts, Buf) ->
                         Low when 16#DC00 =< Low, Low =< 16#DFFF ->
                             Unicode = 16#10000 + (High - 16#D800) * 16#400 + (Low - 16#DC00),
                             string(Bin2, Start, Nexts, unicode_to_utf8(Unicode, Buf));
-                        _ -> ?ERROR(Bin)
+                        _ -> error(badarg, [<<N/binary, Bin/binary>>, Start, Nexts, Buf])
                     end;
-                _ -> ?ERROR(Bin)
+                _ -> error(badarg, [<<N/binary, Bin/binary>>, Start, Nexts, Buf])
             end;
         Unicode when 16#DC00 =< Unicode, Unicode =< 16#DFFF ->  % サロゲートペアの後半部分
-            ?ERROR(<<N/binary, Bin/binary>>);
+            error(badarg, [<<N/binary, Bin/binary>>, Start, Nexts, Buf]);
         Unicode -> 
             string(Bin, Start, Nexts, unicode_to_utf8(Unicode, Buf))
     end;
-unicode_string(<<Bin/binary>>, _Acc, _Nexts, _Buf) ->
-    ?ERROR(Bin).
+unicode_string(Bin, Acc, Nexts, Buf) ->
+    error(badarg, [Bin, Acc, Nexts, Buf]).
 
 -spec unicode_to_utf8(0..1114111, binary()) -> binary().
 unicode_to_utf8(Code, Buf) when Code < 16#80 ->
@@ -191,8 +189,8 @@ number_integer_part(<<$0, Bin/binary>>, Sign, Nexts, Buf) ->
     number_fraction_part(Bin, Sign, 0, Nexts, Buf);
 number_integer_part(<<C, Bin/binary>>, Sign, Nexts, Buf) when $1 =< C, C =< $9 ->
     number_integer_part_rest(Bin, C - $0, Sign, Nexts, Buf);
-number_integer_part(<<Bin/binary>>, _Sign, _Nexts, _Buf) ->
-    ?ERROR(Bin).
+number_integer_part(Bin, Sign, Nexts, Buf) ->
+    error(badarg, [Bin, Sign, Nexts, Buf]).
 
 -spec number_integer_part_rest(binary(), non_neg_integer(), 1|-1, [next()], binary()) -> {jsone:json_value(), Rest::binary()}.
 number_integer_part_rest(<<C, Bin/binary>>, N, Sign, Nexts, Buf) when $0 =< C, C =< $9 ->
@@ -211,8 +209,8 @@ number_fraction_part_rest(<<C, Bin/binary>>, Sign, N, DecimalOffset, Nexts, Buf)
     number_fraction_part_rest(Bin, Sign, N * 10 + C - $0, DecimalOffset + 1, Nexts, Buf);
 number_fraction_part_rest(<<Bin/binary>>, Sign, N, DecimalOffset, Nexts, Buf) when DecimalOffset > 0 ->
     number_exponation_part(Bin, Sign * N, DecimalOffset, Nexts, Buf);
-number_fraction_part_rest(<<Bin/binary>>, _Sign, _N, _DecimalOffset, _Nexts, _Buf) ->
-    ?ERROR(Bin).
+number_fraction_part_rest(Bin, Sign, N, DecimalOffset, Nexts, Buf) ->
+    error(badarg, [Bin, Sign, N, DecimalOffset, Nexts, Buf]).
 
 -spec number_exponation_part(binary(), integer(), non_neg_integer(), [next()], binary()) -> {jsone:json_value(), Rest::binary()}.
 number_exponation_part(<<$e, $+, Bin/binary>>, N, DecimalOffset, Nexts, Buf) ->
@@ -239,5 +237,5 @@ number_exponation_part(<<C, Bin/binary>>, N, DecimalOffset, ExpSign, Exp, _, Nex
 number_exponation_part(<<Bin/binary>>, N, DecimalOffset, ExpSign, Exp, false, Nexts, Buf) ->
     Pos = ExpSign * Exp - DecimalOffset,
     next(Bin, N * math:pow(10, Pos), Nexts, Buf);
-number_exponation_part(<<Bin/binary>>, _N, _DecimalOffset, _ExpSign, _Exp, _IsFirst, _Nexts, _Buf) ->
-    ?ERROR(Bin).
+number_exponation_part(Bin, N, DecimalOffset, ExpSign, Exp, IsFirst, Nexts, Buf) ->
+    error(badarg, [Bin, N, DecimalOffset, ExpSign, Exp, IsFirst, Nexts, Buf]).

+ 46 - 70
src/jsone_encode.erl

@@ -33,6 +33,13 @@
 -export([encode/1]).
 
 %%--------------------------------------------------------------------------------
+%% Macros
+%%--------------------------------------------------------------------------------
+-define(IS_REDUNDANT_UTF8(B1, B2, FirstBitN), (B1 =:= 0 andalso B2 < (1 bsl (FirstBitN + 1)))).
+-define(HEX(N, I), (binary:at(<<"0123456789abcdef">>, (N bsr (I * 4)) band 2#1111))).
+-define(UNICODE_TO_HEX(Code), ?HEX(Code, 3), ?HEX(Code, 2), ?HEX(Code, 1), ?HEX(Code, 0)).
+
+%%--------------------------------------------------------------------------------
 %% Exported Functions
 %%--------------------------------------------------------------------------------
 %% @doc JSON値をバイナリ形式にエンコードする.
@@ -44,89 +51,58 @@ encode(Value) ->
 %% Internal Functions
 %%--------------------------------------------------------------------------------
 -spec value(jsone:json_value(), binary()) -> binary().
-value(null, <<Buf/binary>>)                         -> <<Buf/binary, "null">>;
-value(false, <<Buf/binary>>)                        -> <<Buf/binary, "false">>;
-value(true, <<Buf/binary>>)                         -> <<Buf/binary, "true">>;
-value(Value, <<Buf/binary>>) when is_integer(Value) -> <<Buf/binary, (integer_to_binary(Value))/binary>>;
-value(Value, <<Buf/binary>>) when is_float(Value)   -> <<Buf/binary, (float_to_binary(Value))/binary>>;
-value(Value, <<Buf/binary>>) when is_binary(Value)  -> string(Value, Buf);
-value(Value, <<Buf/binary>>) when is_list(Value)    -> array(Value, Buf);
-value({object, _} = Value, <<Buf/binary>>)          -> object(Value, Buf);
-value(Value, <<_Buf/binary>>)                       -> error(badarg, [Value]).
+value(null, Buf)                         -> <<Buf/binary, "null">>;
+value(false, Buf)                        -> <<Buf/binary, "false">>;
+value(true, Buf)                         -> <<Buf/binary, "true">>;
+value(Value, Buf) when is_integer(Value) -> <<Buf/binary, (integer_to_binary(Value))/binary>>;
+value(Value, Buf) when is_float(Value)   -> <<Buf/binary, (float_to_binary(Value))/binary>>;
+value(Value, Buf) when is_binary(Value)  -> string(Value, Buf);
+value(Value, Buf) when is_list(Value)    -> array(Value, Buf);
+value({object, _} = Value, Buf)          -> object(Value, Buf);
+value(Value, Buf)                        -> error(badarg, [Value, Buf]).
 
 -spec string(jsone:json_string(), binary()) -> binary().
-string(<<Str/binary>>, <<Buf/binary>>) ->
+string(<<Str/binary>>, Buf) ->
     escape_string(Str, <<Buf/binary, $">>).
 
 -spec escape_string(binary(), binary()) -> binary().
-escape_string(<<"">>, <<Buf/binary>>) ->
-    <<Buf/binary, $">>;
-escape_string(<<$", Str/binary>>, <<Buf/binary>>) ->
-    escape_string(Str, <<Buf/binary, $\\, $">>);
-escape_string(<<$\/, Str/binary>>, <<Buf/binary>>) ->
-    escape_string(Str, <<Buf/binary, $\\, $\/>>);
-escape_string(<<$\\, Str/binary>>, <<Buf/binary>>) ->
-    escape_string(Str, <<Buf/binary, $\\, $\\>>);
-escape_string(<<$\b, Str/binary>>, <<Buf/binary>>) ->
-    escape_string(Str, <<Buf/binary, $\\, $b>>);
-escape_string(<<$\f, Str/binary>>, <<Buf/binary>>) ->
-    escape_string(Str, <<Buf/binary, $\\, $f>>);
-escape_string(<<$\n, Str/binary>>, <<Buf/binary>>) ->
-    escape_string(Str, <<Buf/binary, $\\, $n>>);
-escape_string(<<$\r, Str/binary>>, <<Buf/binary>>) ->
-    escape_string(Str, <<Buf/binary, $\\, $r>>);
-escape_string(<<$\t, Str/binary>>, <<Buf/binary>>) ->
-    escape_string(Str, <<Buf/binary, $\\, $t>>);
-escape_string(<<C, Str/binary>>, <<Buf/binary>>) when C < 16#80 ->
-    escape_string(Str, <<Buf/binary, C>>);
-escape_string(<<2#10:2, _:6, _/binary>> = Str, <<Buf/binary>>) ->
-    error(badarg, [Str, Buf]);
-escape_string(<<2#110:3, B1:5, 2#10:2, B2:6, Str/binary>> = Str0, <<Buf/binary>>) ->
-    case is_redundant_utf8_byte(B1, B2, 5) of
-        true  -> error(badarg, [Str0, Buf]);
-        false -> 
-            Unicode = (B1 bsl 6) + B2,
-            escape_unicode_char(Str, Unicode, Buf)
-    end;
-escape_string(<<2#1110:4, B1:4, 2#10:2, B2:6, 2#10:2, B3:6, Str/binary>> = Str0, <<Buf/binary>>) ->
-    case is_redundant_utf8_byte(B1, B2, 4) of
-        true  -> error(badarg, [Str0, Buf]);
-        false ->
-            Unicode = (B1 bsl 12) + (B2 bsl 6) + B3,
-            escape_unicode_char(Str, Unicode, Buf)
-    end;
-escape_string(<<2#11110:5, B1:3, 2#10:2, B2:6, 2#10:2, B3:6, 2#10:2, B4:6, Str/binary>> = Str0, <<Buf/binary>>) ->
-    case is_redundant_utf8_byte(B1, B2, 3) of
-        true  -> error(badarg, [Str0, Buf]);
-        false ->
-            Unicode = (B1 bsl 18) + (B2 bsl 12) + (B3 bsl 6) + B4,
-            escape_unicode_char(Str, Unicode, Buf)
-    end;    
-escape_string(<<Str/binary>>, <<Buf/binary>>) ->
+escape_string(<<"">>,                   Buf) -> <<Buf/binary, $">>;
+escape_string(<<$", Str/binary>>,       Buf) -> escape_string(Str, <<Buf/binary, $\\, $">>);
+escape_string(<<$\/, Str/binary>>,      Buf) -> escape_string(Str, <<Buf/binary, $\\, $\/>>);
+escape_string(<<$\\, Str/binary>>,      Buf) -> escape_string(Str, <<Buf/binary, $\\, $\\>>);
+escape_string(<<$\b, Str/binary>>,      Buf) -> escape_string(Str, <<Buf/binary, $\\, $b>>);
+escape_string(<<$\f, Str/binary>>,      Buf) -> escape_string(Str, <<Buf/binary, $\\, $f>>);
+escape_string(<<$\n, Str/binary>>,      Buf) -> escape_string(Str, <<Buf/binary, $\\, $n>>);
+escape_string(<<$\r, Str/binary>>,      Buf) -> escape_string(Str, <<Buf/binary, $\\, $r>>);
+escape_string(<<$\t, Str/binary>>,      Buf) -> escape_string(Str, <<Buf/binary, $\\, $t>>);
+escape_string(<<0:1, C:7, Str/binary>>, Buf) -> escape_string(Str, <<Buf/binary, C>>);
+escape_string(<<2#110:3, B1:5, 2#10:2, B2:6, Str/binary>>, Buf) when not ?IS_REDUNDANT_UTF8(B1, B2, 5) ->
+    Unicode = (B1 bsl 6) + B2,
+    escape_unicode_char(Str, Unicode, Buf);
+escape_string(<<2#1110:4, B1:4, 2#10:2, B2:6, 2#10:2, B3:6, Str/binary>>, Buf) when not ?IS_REDUNDANT_UTF8(B1, B2, 4) ->
+    Unicode = (B1 bsl 12) + (B2 bsl 6) + B3,
+    escape_unicode_char(Str, Unicode, Buf);
+escape_string(<<2#11110:5, B1:3, 2#10:2, B2:6, 2#10:2, B3:6, 2#10:2, B4:6, Str/binary>>, Buf) when not ?IS_REDUNDANT_UTF8(B1, B2, 3) ->
+    Unicode = (B1 bsl 18) + (B2 bsl 12) + (B3 bsl 6) + B4,
+    escape_unicode_char(Str, Unicode, Buf);
+escape_string(Str, Buf) ->
     error(badarg, [Str, Buf]).
 
--spec is_redundant_utf8_byte(byte(), byte(), 3..5) -> boolean().
-is_redundant_utf8_byte(B1, B2, FirstBitN) ->
-    B1 =:= 0 andalso B2 < (1 bsl (FirstBitN+1)).
-
--define(HEX(N, I), (binary:at(<<"0123456789abcdef">>, (N bsr (I * 4)) band 2#1111))).
--define(UNICODE_TO_HEX(Code), ?HEX(Code, 3), ?HEX(Code, 2), ?HEX(Code, 1), ?HEX(Code, 0)).
-
 -spec escape_unicode_char(binary(), char(), binary()) -> binary().
-escape_unicode_char(<<Str/binary>>, Unicode, <<Buf/binary>>) when Unicode =< 16#FFFF ->
+escape_unicode_char(<<Str/binary>>, Unicode, Buf) when Unicode =< 16#FFFF ->
     escape_string(Str, <<Buf/binary, $\\, $u, ?UNICODE_TO_HEX(Unicode)>>);
-escape_unicode_char(<<Str/binary>>, Unicode, <<Buf/binary>>) ->
+escape_unicode_char(<<Str/binary>>, Unicode, Buf) ->
     %% サロゲートペア
     <<High:10, Low:10>> = <<(Unicode - 16#10000):20>>, % 非効率
     escape_string(Str, <<Buf/binary, $\\, $u, ?UNICODE_TO_HEX(High + 16#D800), $\\, $u, ?UNICODE_TO_HEX(Low + 16#DC00)>>).
 
 -spec array(jsone:json_array(), binary()) -> binary().
-array(List, <<Buf/binary>>) ->
+array(List, Buf) ->
     array_values(List, <<Buf/binary, $[>>).
 
 -spec array_values(jsone:json_array(), binary()) -> binary().
-array_values([],       <<Buf/binary>>) -> <<Buf/binary, $]>>;
-array_values([X | Xs], <<Buf/binary>>) ->
+array_values([],       Buf) -> <<Buf/binary, $]>>;
+array_values([X | Xs], Buf) ->
     Buf2 = value(X, Buf),
     case Xs of
         [] -> <<Buf2/binary, $]>>;
@@ -134,17 +110,17 @@ array_values([X | Xs], <<Buf/binary>>) ->
     end.
 
 -spec object(jsone:json_object(), binary()) -> binary().
-object({object, Members}, <<Buf/binary>>) ->
+object({object, Members}, Buf) ->
     object_members(Members, <<Buf/binary, ${>>).
 
 -spec object_members(jsone:json_object_members(), binary()) -> binary().
-object_members([],                             <<Buf/binary>>) -> <<Buf/binary, $}>>;
-object_members([{<<Key/binary>>, Value} | Xs], <<Buf/binary>>) ->
+object_members([],                             Buf) -> <<Buf/binary, $}>>;
+object_members([{<<Key/binary>>, Value} | Xs], Buf) ->
     Buf2 = string(Key, Buf),
     Buf3 = value(Value, <<Buf2/binary, $:>>),
     case Xs of
         [] -> <<Buf3/binary, $}>>;
         _  -> object_members(Xs, <<Buf3/binary, $,>>)
     end;
-object_members(Arg, <<Buf/binary>>) ->
+object_members(Arg, Buf) ->
     error(badarg, [Arg, Buf]).

+ 24 - 24
test/jsone_decode_tests.erl

@@ -45,7 +45,7 @@ decode_test_() ->
       end},
      {"正の整数の前の'+'記号は許可されない",
       fun () ->
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"+1">>))
+              ?assertError(badarg, jsone_decode:decode(<<"+1">>))
       end},
 
      %% 数値系: 小数
@@ -65,13 +65,13 @@ decode_test_() ->
       end},
      {"不正な形式の小数",
       fun () ->
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<".123">>)),  % 整数部が省略されている
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"0.">>)),    % '.'の後ろに小数部が続かない
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"0.e+3">>)), % '.'の後ろに指数部が来る
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"0.1e">>)),    % 指数部が欠けている
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"0.1e-">>)),   % 指数部が欠けている
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"0.1ee-1">>)), % 'e'が複数ある
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"0.1e--1">>)), % 符号が複数ある
+              ?assertError(badarg, jsone_decode:decode(<<".123">>)),  % 整数部が省略されている
+              ?assertError(badarg, jsone_decode:decode(<<"0.">>)),    % '.'の後ろに小数部が続かない
+              ?assertError(badarg, jsone_decode:decode(<<"0.e+3">>)), % '.'の後ろに指数部が来る
+              ?assertError(badarg, jsone_decode:decode(<<"0.1e">>)),    % 指数部が欠けている
+              ?assertError(badarg, jsone_decode:decode(<<"0.1e-">>)),   % 指数部が欠けている
+              ?assertError(badarg, jsone_decode:decode(<<"0.1ee-1">>)), % 'e'が複数ある
+              ?assertError(badarg, jsone_decode:decode(<<"0.1e--1">>)), % 符号が複数ある
               ?assertEqual({0.1, <<".2">>}, jsone_decode:decode(<<"0.1.2">>))  % '.'が複数ある => 別々のトークンと判断される
       end},
      
@@ -111,11 +111,11 @@ decode_test_() ->
       end},
      {"不正なエスケープ文字",
       fun () ->
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"\"\\z\"">>)),    % '\z'は未定義のエスケープ文字
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"\"\\uab\"">>)),  % '\u'の後ろに続く数値が足りない
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"\"\\ud848\"">>)), % 上位サロゲートが単独で出現
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"\"\\udc49\"">>)), % 下位サロゲーが単独で出現
-              ?assertError({invalid_json, _}, jsone_decode:decode(<<"\"\\ud848\\u0061\"">>)) % 上位サロゲートの後ろに下位サロゲートが続かない
+              ?assertError(badarg, jsone_decode:decode(<<"\"\\z\"">>)),    % '\z'は未定義のエスケープ文字
+              ?assertError(badarg, jsone_decode:decode(<<"\"\\uab\"">>)),  % '\u'の後ろに続く数値が足りない
+              ?assertError(badarg, jsone_decode:decode(<<"\"\\ud848\"">>)), % 上位サロゲートが単独で出現
+              ?assertError(badarg, jsone_decode:decode(<<"\"\\udc49\"">>)), % 下位サロゲーが単独で出現
+              ?assertError(badarg, jsone_decode:decode(<<"\"\\ud848\\u0061\"">>)) % 上位サロゲートの後ろに下位サロゲートが続かない
       end},
 
      %% 配列系
@@ -133,24 +133,24 @@ decode_test_() ->
      {"配列の末尾のカンマは許容されない",
       fun () ->
               Input = <<"[1, 2, \"abc\", null, ]">>,
-              ?assertError({invalid_json, _}, jsone_decode:decode(Input))
+              ?assertError(badarg, jsone_decode:decode(Input))
       end},
      {"区切り文字のカンマが抜けているとエラーとなる",
       fun () ->
               Input = <<"[1 2, \"abc\", null]">>, % 1と2の間にカンマがない
-              ?assertError({invalid_json, _}, jsone_decode:decode(Input))
+              ?assertError(badarg, jsone_decode:decode(Input))
       end},
      {"配列が閉じていないとエラー",
       fun () ->
               Input = <<"[1, 2, \"abc\", null">>,
-              ?assertError({invalid_json, _}, jsone_decode:decode(Input))
+              ?assertError(badarg, jsone_decode:decode(Input))
       end},
 
      %% オブジェクト系
      {"オブジェクトがデコード可能",
       fun () ->
               Input    = <<"{\"1\":2, \"key\":\"value\"}">>,
-              Expected = {object, [{<<"1">>, 2}, {<<"key">>, <<"value">>}]},
+              Expected = {object, [{<<"key">>, <<"value">>}, {<<"1">>, 2}]},
               ?assertEqual({Expected, <<"">>}, jsone_decode:decode(Input))
       end},
      {"空オブジェクトがデコード可能",
@@ -162,39 +162,39 @@ decode_test_() ->
       fun () ->
               Input = <<"{\"1\":2, \"key\":\"value\", }">>,
               io:format("~p\n", [catch jsone_decode:decode(Input)]),
-              ?assertError({invalid_json, _}, jsone_decode:decode(Input))
+              ?assertError(badarg, jsone_decode:decode(Input))
       end},
      {"区切り文字のカンマが抜けているとエラーとなる",
       fun () ->
               Input = <<"{\"1\":2 \"key\":\"value\"}">>,
-              ?assertError({invalid_json, _}, jsone_decode:decode(Input))
+              ?assertError(badarg, jsone_decode:decode(Input))
       end},
      {"メンバのキーがない場合はエラー",
       fun () ->
               Input = <<"{:2, \"key\":\"value\"}">>,
-              ?assertError({invalid_json, _}, jsone_decode:decode(Input))
+              ?assertError(badarg, jsone_decode:decode(Input))
       end},
      {"メンバのキーが文字列以外の場合はエラー",
       fun () ->
               Input = <<"{1:2, \"key\":\"value\"}">>,
-              ?assertError({invalid_json, _}, jsone_decode:decode(Input))
+              ?assertError(badarg, jsone_decode:decode(Input))
       end},
      {"メンバの値がない場合はエラー",
       fun () ->
               Input = <<"{\"1\", \"key\":\"value\"}">>,
-              ?assertError({invalid_json, _}, jsone_decode:decode(Input))
+              ?assertError(badarg, jsone_decode:decode(Input))
       end},
      {"オブジェクトが閉じていないとエラー",
       fun () ->
               Input = <<"{\"1\":2 \"key\":\"value\"">>,
-              ?assertError({invalid_json, _}, jsone_decode:decode(Input))
+              ?assertError(badarg, jsone_decode:decode(Input))
       end},
 
      %% その他
      {"複雑なデータがデコード可能",
       fun () ->
               Input    = <<"  [true, {\"1\" : 2, \"array\":[[[[1]]], {\"ab\":\"cd\"}, false]}, null]   ">>,
-              Expected = [true, {object, [{<<"1">>, 2}, {<<"array">>, [[[[1]]], {object, [{<<"ab">>, <<"cd">>}]}, false]}]}, null],
+              Expected = [true, {object, [{<<"array">>, [[[[1]]], {object, [{<<"ab">>, <<"cd">>}]}, false]}, {<<"1">>, 2}]}, null],
               ?assertEqual({Expected, <<"   ">>}, jsone_decode:decode(Input))
       end}
     ].