view julia/parallel/ParallelProcessing/src/json.jl @ 36:03d20a4dd8f2

json: metaparser
author Lewin Bormann <lbo@spheniscida.de>
date Fri, 24 Mar 2023 21:30:03 +0100
parents 8208faa6c42f
children
line wrap: on
line source

using JSON
using Random
import Base.Threads

struct Details
    level::String
    kind::Int
end

"""Example for a method that can be derived straight from a struct definition and parses just a struct
            from a JSON object."""
function take_struct!(::Type{Details}, jp::JP)::Union{Nothing,Details}
    expect!(jp, '{') || return nothing

    level::Union{Nothing,String} = nothing
    kind::Union{Nothing,Int} = nothing
    while true
        key = take_str!(jp)
        if isnothing(key)
            break
        end

        expect!(jp, ':') || error("malformed object - expected ':'")

        # Custom code!
        if key == "level"
            level = take_str!(jp)
        elseif key == "kind"
            kind = take_num!(jp)
        else
            # Ignore unknown keys
            take_val!(jp)
        end

        if expect!(jp, ',')
            continue
        else
            break
        end
    end

    if isnothing(level) || isnothing(kind)
        error("Elements missing from object: $level, $kind")
    end

    expect!(jp, '}') || error("unclosed Details object")

    Details(level, kind)
end

struct SimpleEntry
    s::String
    a::Int
    f::Float64
    details::Details
end

function generate_entry()::SimpleEntry
    s, level = randstring(20), randstring(10)
    a, kind = rand(Int, 2)
    f = rand()
    SimpleEntry(s, a, f, Details(level, kind))
end

function generate_json(file, n = 1000)
    open(file; write = true) do fh
        for i = 1:n
            println(fh, json(generate_entry()))
        end
    end
end

fib(n) =
    if n <= 2
        1
    else
        fib(n - 1) + fib(n - 2)
    end

function expensive_mapper(m::Dict)::Int
    i = abs(m["a"]) % 35
    fib(i)
end

function process_json(file, mapper = x -> ())::Vector
    open(file; read = true) do fh
        [mapper(JSON.parse(line)) for line in eachline(fh)]
    end
end


function process_json_parallel(file, mapper = x -> ())::Vector
    open(file; read = true) do fh
        ch = Channel(100)
        count = 0
        for line in eachline(fh)
            Threads.@spawn put!(ch, mapper(JSON.parse(line)))
            count += 1
        end
        [take!(ch) for i = 1:count]
    end
end