json: returning list / string

47 views
Skip to first unread message

ryuj...@gmail.com

unread,
Oct 20, 2014, 2:42:55 AM10/20/14
to chica...@googlegroups.com


Hi everyone.

Saw similar, but unanswered questions.

When returning json from a controller, the browser often gets arrays instead of strings (even from tutorial examples, "greeting-N" always becomes an array) and vice versa. How do you control this behavior?

can2nac

unread,
Oct 26, 2014, 11:26:25 AM10/26/14
to chica...@googlegroups.com
"string" is an "array", store binaries instead "strings" (<<"string">>) or change type before parsing into erlydtl  

Jitin Luthra

unread,
Oct 26, 2014, 12:19:26 PM10/26/14
to chica...@googlegroups.com
I don't know if its the best way but I use this:

Instead of 
{json, [{error,(ErrorList)}]}

I use:
{json, [{error,list_to_binary(ErrorList)}]}

This also seems to work:

{json, [{error,io_lib:write_string(ErrorList)}]}

I think the list_to_binary method cannot convert unicode characters (http://www.erlang.org/doc/man/unicode.html) so for that case you could need to use

{json, [{error,unicode:characters_to_binary(ErrorList)}]}


Someone please correct me if I am wrong.
Thanks,
Jitin

can2nac

unread,
Oct 27, 2014, 12:29:42 PM10/27/14
to chica...@googlegroups.com
ErrorList must be [<<"error1">>,<<"error2">>], how you get it is another question. As far as i remember list of atoms work as well

Jitin Luthra

unread,
Oct 28, 2014, 6:20:43 AM10/28/14
to chica...@googlegroups.com
Hi,
Thanks for the correction. I use these for the model validation function which returns a list of strings called ErrorMessages if validation fails:
{error, [ErrorMessages]}
It works in this case.

Thanks

can2nac

unread,
Oct 28, 2014, 11:03:52 AM10/28/14
to chica...@googlegroups.com
i use it in the same instance and validation function returns binary string, not the list, for example <<"name">>

Jitin Luthra

unread,
Oct 28, 2014, 12:08:09 PM10/28/14
to chica...@googlegroups.com
Hi,

The validation function returns {error, [ErrorMessages]}

What I do is that I receive it in {error,ErrorList}
I think this is what makes ErrorList a list.

I think what you are doing is that you are receiving it as {error,[ErrorList]}
and then doing a {json,[{error,ErrorList}]}
This would work fine if you knew for sure there was only one validation error. But when you have more than one validation errors then I think this code will break.

In my case, I can get more than one validation errors.
Hence, I have to receive it as a list - {error,ErrorList}
But if I directly json it, I get an array of numbers in output.
So, I instead do {json, [{error,list_to_binary(ErrorList)}]}

This works in my case, giving a string json output.
What also works is this: {json, [{error,io_lib:write_string(ErrorList)}]}

In the previous mail I had also mentioned unicode:character_to_binary. That however does not seem to work in case of a list of more than one error strings so that was incorrect.

Please forgive me if I misunderstood you - I am new to Chicago Boss (and Erlang) :)

Thanks
Jitin

can2nac

unread,
Oct 29, 2014, 7:15:26 PM10/29/14
to chica...@googlegroups.com
The validation function returns {error, [ErrorMessages]} - correct if u have only one error
It returns {error, [Error1, Error2, ..., ErrorN]} in general


validation_tests() -> [
{fun()-> false end, <<"email">>},
{fun()-> false end, <<"password">>},
].

case ....:save() of
{ok, _} ->
{error, E} -> {render_other, [{action,"show"}], [{errors, E}]} % or {json, [{errors, E}]}
end


On frontend don't forget to check name against array of errors, so this will not work if we consider given above case {% if email == errors %} has-error {% endif %}

I use custom tag for this {%if errors|has:"email"%}has-error{%endif%}

has(undefined,_)->false;
has([],_)->false;
has(Errors,Key)->has(Errors,Key,false).

has(_,_,true)->true;
has([],_,Res)->Res;
has([H|T],Key,_)->has(T,Key,H=:=Key).



On Monday, October 20, 2014 10:42:55 AM UTC+4, Alex V wrote:

Jitin

unread,
Oct 30, 2014, 9:50:57 AM10/30/14
to chica...@googlegroups.com
Hi,

Sorry for the confusion. Now I get it - you directly specify your validation messages to be binary strings. In my case I was specifying them as regular list-strings - like:
[{fun()->length(UserPassword)>7 end,"Password length must at least 8! <br>"},
{fun()->length(UserEmail)>5 end, "Invalid E-mail address! <br>"},
         {fun()->boss_db:find(user_record,[{user_email,'equals',string:to_lower(UserEmail)},{id,'not_in',[Id]}])==[] end, "This e-mail address is already registered! <br>"}].

So in this case when I do
case ....:save() of
{ok, _} ->
{error, E} -> {json, [{errors, E}]}
end

then the json output is an array of numbers instead of strings
{
    "errors": [
        [
            80,
            97,
            115,
            115,
            119,
            111,
            114,
            100,
            32,
            108,
            101,
            110,
            103,
            116,
            104,
            32,
            109,
            117,
            115,
            116,
            32,
            97,
            116,
            32,
            108,
            101,
            97,
            115,
            116,
            32,
            56,
            33,
            32,
            60,
            98,
            114,
            62
        ],
        [
            84,
            104,
            105,
            115,
            32,
            101,
            45,
            109,
            97,
            105,
            108,
            32,
            97,
            100,
            100,
            114,
            101,
            115,
            115,
            32,
            105,
            115,
            32,
            97,
            108,
            114,
            101,
            97,
            100,
            121,
            32,
            114,
            101,
            103,
            105,
            115,
            116,
            101,
            114,
            101,
            100,
            33,
            32,
            60,
            98,
            114,
            62
        ]
    ]
}



So, I have to do this instead: 
case ....:save() of
{ok, _} ->
{error, E} -> {json, [{errors, list_to_binary(E)}]}
end
This gives the correct json output:
{
    "errors": "Password length must at least 8! <br>This e-mail address is already registered! <br>"
}

This is why I had suggested the list_to_binary or the io_lib:write_string function -- to convert the numbered lists into binary again.

But since you keep them in binary by default you have no need of this conversion. Obviously it is better to keep it in binary by default like you do to avoid the extra conversion step. But if that's not possible for someone then I guess they would have to use the list_to_binary function.

Since OP was also getting numbers instead of characters in JSON and list_to_binary is what I used in my case - hence I suggested that.
Sorry again for the confusion - I was only trying to help :)

Thanks

can2nac

unread,
Oct 31, 2014, 11:43:45 AM10/31/14
to chica...@googlegroups.com
"{error, E} -> {json, [{errors, list_to_binary(E)}]}" is correct only when u have 1 error, otherwise it will crash

Why u can's simply use binary strings?

[{fun()->length(UserPassword)>7 end,<<"Password length must at least 8! <br>">>},
 {fun()->length(UserEmail)>5 end, <<"Invalid E-mail address! <br>">>},
         {fun()->boss_db:find(user_record,[{user_email,'equals',string:to_lower(UserEmail)},{id,'not_in',[Id]}])==[] end, <<"This e-mail address is already registered! <br>">>}].

P.S. I'm just curious, what id stands for?

can2nac

unread,
Oct 31, 2014, 11:45:22 AM10/31/14
to chica...@googlegroups.com
oh, disregret my comment, i've just noticed how u build error string

"errors": "Password length must at least 8! <br>This e-mail address is already registered! <br>"

now it is clear.

On Monday, October 20, 2014 9:42:55 AM UTC+3, Alex V wrote:
Reply all
Reply to author
Forward
0 new messages