3

I have a Erlang list of tuples as follows:

[  {{"a"},[2],[{3,"b"},{4,"c"}],[5,"d"],[1,1],{e},["f"]}  , 
   {{"g"},[3],[{6,"h"},{7,"i"}],[{8,"j"}],[1,1,1],{k},["L"]}  ]

I wanted this list of tuples in this form:

<<" [  {{"a"},[2],[{3,"b"},{4,"c"}],[5,"d"],[1,1],{e},["f"]} , 
       {{"g"},[3],[{6,"h"},{7,"i"}],[{8,"j"}],[1,1,1],{k},["L"]}] ">>

So I tried using JSON parsing libraries in erlang (both jiffy and jsx ) Here is what I did:

A=[  {{"a"},[2],[{3,"b"},{4,"c"}],[5,"d"],[1,1],{e},["f"]}  , 
       {{"g"},[3],[{6,"h"},{7,"i"}],[{8,"j"}],[1,1,1],{k},["L"]}  ],

B=erlang:iolist_to_binary(io_lib:write(A)),

jsx:encode(B).

and I get the following output(here I have changed the list to binary since jsx accepts binary):

 <<"[{{[97]},[2],[{3,[98]},{4,[99]}],[5,[100]],[1,1],{e},[[102]]},{{[103]},
 [3],[{6,[104]},{7,[105]}],[{8,[106]}],[1,1,1],{k},[[76]]}]">>

jiffy:encode(B) also gives the same output. Can anyone help me to get the output as :

<<" [  {{"a"},[2],[{3,"b"},{4,"c"}],[5,"d"],[1,1],{e},["f"]} , 
           {{"g"},[3],[{6,"h"},{7,"i"}],[{8,"j"}],[1,1,1],{k},["L"]}] ">>

instead of

<<"[{{[97]},[2],[{3,[98]},{4,[99]}],[5,[100]],[1,1],{e},[[102]]},{{[103]},
     [3],[{6,[104]},{7,[105]}],[{8,[106]}],[1,1,1],{k},[[76]]}]">>

Thank you in advance

abhishek ranjan
  • 612
  • 7
  • 23

2 Answers2

3

Instead of io_lib:write(A), use io_lib:format("~p", [A]). It tries to guess which lists are actually meant to be strings. (In Erlang, strings are actually lists of integers. Try it: "A" == [65])

> A=[  {{"a"},[2],[{3,"b"},{4,"c"}],[5,"d"],[1,1],{e},["f"]}  ,
       {{"g"},[3],[{6,"h"},{7,"i"}],[{8,"j"}],[1,1,1],{k},["L"]}  ].
[{{"a"},[2],[{3,"b"},{4,"c"}],[5,"d"],[1,1],{e},["f"]},
 {{"g"},[3],[{6,"h"},{7,"i"}],[{8,"j"}],[1,1,1],{k},["L"]}]
> B = erlang:iolist_to_binary(io_lib:format("~p", [A])).
<<"[{{\"a\"},[2],[{3,\"b\"},{4,\"c\"}],[5,\"d\"],[1,1],{e},[\"f\"]},\n {{\"g\"},[3],[{6,\"h\"},{7,\"i\"}],[{8,\"j\"}],[1,1,1],{k},[\"L\"]}]">>

If you don't want to see the backslashes before the double quotes, you can print the string to standard output:

> io:format("~s\n", [B]).
[{{"a"},[2],[{3,"b"},{4,"c"}],[5,"d"],[1,1],{e},["f"]},
 {{"g"},[3],[{6,"h"},{7,"i"}],[{8,"j"}],[1,1,1],{k},["L"]}]
legoscia
  • 39,593
  • 22
  • 116
  • 167
  • thank you for the reply. Sorry I misunderstood your answer. Now I understood that you suggested to use io:format("~s\n",[B]) separately. But currently I am getting a output like <<"[{{\"a\"},[2],[{3,\"b\"},{4,\"c\"}],[5,\"d\"],[1,1],{e},[\"f\"]},\n {{\"g\"},[3],[{6,\"h\"},{7,\"i\"}],[{8,\"j\"}],[1,1,1],{k},[\"L\"]}]">>. Is there any way to get the data without the slashes but as a binary string like <<" ">>. The option to use io:format("~s\n") also removes <<" ">>, but I want it too. Also I wanted to get rid of the '\n' too that are getting generated.Kindly suggest something – abhishek ranjan Aug 22 '17 at 13:50
  • To get the string without `\n`, you can do something like `io_lib:format("~1000p", [A])` - that will only add newlines if the output is longer than 1000 characters; not sure if there's a way to do it without the limit. You can print it with `io:format("<<\"~s\">>\n", [B])` to get the `<<"` and `">>` markers without escaping the double quotes in the middle. – legoscia Aug 22 '17 at 14:22
  • thank you @legiscia, using limit is working as of now. – abhishek ranjan Aug 23 '17 at 07:18
3

<<" [ {{"a"},[2],[{3,"b"},{4,"c"}],[5,"d"],[1,1],{e},["f"]} , {{"g"},[3],[{6,"h"},{7,"i"}],[{8,"j"}],[1,1,1],{k},["L"]}] ">>

This ^^ isn't a valid erlang term, but I think what you're getting at is that you want the "listy" strings, like "a" to be printed out like "a" instead of [97]. Unfortunately, I've found this to be a serious shortcoming of Erlang. The problem is that the string literal "a" is only syntactic sugar and is identical to the term [97], so any time you output it, you're subject to the vagaries of "is this thing a string or a list of integers?" The best way I know to get out of that is to use binaries as your strings wherever possible, like <<"a">> instead of "a".

Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199