I’d try to use the built-in tools for iterating and transforming stuff to 
make the code a little terser and easier to read:

function df2json(df)
    io = IOBuffer()
    write(io, "[\n")
    write(io, join(map(row -> "{\"A\": $(row[:A]), \"B\": \"$(row[:B])\"}", 
eachrow(d)), ",\n"))
    write(io, "\n]\n")
    json = takebuf_string(io)
    close(io)
    json
end

The keys here is to use the map and eachrow functions to get rid of the for 
loops, and to build each item with string interpolation, which makes it 
easier to see what the result will be.
Note that I end the entire message with a newline; I think this is good 
practice in any string buffer protocol.

Next, I’d split the handling of the IO buffer away from the rest:

function df2json(df)
    io = IOBuffer()
    df2json(io, df)
    json = takebuf_string(io)
    close(io)
    json
end

function df2json(io::IO, df)
    write(io, "[\n")
    write(io, join(map(row -> "{\"A\": $(row[:A]), \"B\": \"$(row[:B])\"}", 
eachrow(d)), ",\n"))
    write(io, "\n]\n")
end

I’d also make pretty-printing optional, to make it possible to write the 
JSON as compact as possible too:

function df2json(df; pretty_print::Bool=false)
    io = IOBuffer()
    df2json(io, df; pretty_print=pretty_print)
    json = takebuf_string(io)
    close(io)
    json
end

function df2json(io::IO, df; pretty_print::Bool=false)
    write(io, "[")
    pretty_print && write(io, "\n")
    separator = "," * (pretty_print ? "\n\t" : "")
    space = pretty_print ? " " : ""
    write(io, join(map(row -> 
"{\"A\":$space$(row[:A]),$space\"B\":$space\"$(row[:B])\"}", eachrow(d)), 
separator))
    pretty_print && write(io, "\n")
    write(io, "]")
    write(io, "\n")
end

Now, this allows you to print the message either for human reading:

julia> d = DataFrame(A=1:10, B=map(x -> x > 0.5 ? "F" : "M", rand(10)))
10x2 DataFrames.DataFrame
| Row | A  | B   |
|-----|----|-----|
| 1   | 1  | "M" |
| 2   | 2  | "M" |
| 3   | 3  | "M" |
| 4   | 4  | "M" |
| 5   | 5  | "F" |
| 6   | 6  | "F" |
| 7   | 7  | "F" |
| 8   | 8  | "M" |
| 9   | 9  | "F" |
| 10  | 10 | "F" |

julia> println(df2json(d; pretty_print=true));
[
        {"A": 1, "B": "M"},
        {"A": 2, "B": "M"},
        {"A": 3, "B": "M"},
        {"A": 4, "B": "M"},
        {"A": 5, "B": "F"},
        {"A": 6, "B": "F"},
        {"A": 7, "B": "F"},
        {"A": 8, "B": "M"},
        {"A": 9, "B": "F"},
        {"A": 10, "B": "F"}
]

or for minimizing network overhead:

julia> println(df2json(d))
[{"A":1,"B":"M"},{"A":2,"B":"M"},{"A":3,"B":"M"},{"A":4,"B":"M"},{"A":5,"B":"F"},{"A":6,"B":"F"},{"A":7,"B":"F"},{"A":8,
"B":"M"},{"A":9,"B":"F"},{"A":10,"B":"F"}]

// T

On Monday, November 9, 2015 at 6:12:31 AM UTC+1, Eric Forgy wrote:

This is embarrassing since I'm just learning, but in the interest of 
> getting feedback and improving my Julia coding skills, here is what I did:
>
> function df2json(df::DataFrame)
>
> nrow,ncol = size(df)
>
> io = IOBuffer();
> write(io,"[\n")
> for irow = 1:nrow
>   irow == nrow ? eor = "" : eor = ","
>   write(io,"{")
>   for icol = 1:ncol
>     icol == ncol ? eoe = "" : eoe = ","
>     sym = names(df)[icol]
>     name = string(sym)
>     if isa(value,Number)
>       write(io,"\""*name*"\":"*string(df[irow,sym])*eoe)
>     else
>       write(io,"\""*name*"\":\""*df[irow,sym]*"\""*eoe)
>     end
>   end
>   write(io,"}"*eor*"\n")
> end
> write(io,"]\n")
>
> json = takebuf_string(io)
> close(io)
> json
> end
>
>
> Any thoughts/suggestions? Thank you.
>
​

Reply via email to