Need help with your JSON?
Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool
Julia Language: JSON Parsing and Formatting
If you need to work with JSON in Julia today, the shortest path is usually JSON.jl: parse a string or file with JSON.parse, format data with JSON.json, and switch to typed or lazy parsing when the payload gets more complex. This page focuses on the current JSON.jl API, because some older Julia JSON tutorials still describe outdated defaults.
For searchers looking for the right Julia JSON package: JSON.jl is a strong default for general parsing, formatting, JSON Lines, and direct struct decoding. If your codebase already uses JSON3.jl and StructTypes, staying consistent with that stack is also reasonable.
Getting Started with JSON.jl
Install the package once with Julia's package manager, then import it in your project or REPL session:
Install and import
julia> using Pkg
julia> Pkg.add("JSON")
julia> using JSONThe core functions you will use most are JSON.parse, JSON.parsefile, JSON.json, and JSON.print.
Parsing JSON into Julia Values
JSON.parse eagerly reads a JSON string and converts it into Julia values. The important current detail is that JSON objects parse to JSON.Object{String, Any} by default, not a plain Dict.
- JSON objects become
JSON.Object{String, Any}, which preserves insertion order and is designed to feel close to a dictionary. - JSON arrays become
Vector{Any}. - JSON strings become
String. - JSON numbers become an appropriate Julia number type such as
Int64,BigInt,Float64, orBigFloat. - JSON booleans become
Bool. - JSON
nullbecomesnothing.
Basic parsing example
json_text = """
{
"name": "Alice",
"age": 30,
"active": true,
"tags": ["julia", "json"],
"profile": {
"city": "Vilnius",
"country": "Lithuania"
},
"score": null
}
"""
data = JSON.parse(json_text)
println(typeof(data)) # JSON.Object{String, Any}
println(data["name"]) # Alice
println(data["tags"][1]) # julia
println(data["profile"]["city"]) # Vilnius
println(data["score"] === nothing) # trueIf a key is also a valid Julia identifier, JSON.Object supports dot-style access too, so data.profile can be convenient in scripts and notebooks.
When to parse into a Dict instead
The default JSON.Object is order-preserving, but key lookups are linear rather than hashed. If you are going to hit the same large object many times, parse into a dictionary up front:
data = JSON.parse(json_text; dicttype=Dict{String, Any})
println(typeof(data)) # Dict{String, Any}
println(data["profile"]["city"]) # VilniusThat small option is one of the most useful performance tips when working with bigger Julia JSON payloads.
Parsing directly into structs
Modern JSON.jl can decode JSON straight into your own types, which is often cleaner than pushing around Dict{String, Any} values everywhere.
struct Author
name::String
github::String
end
json_text = """{"name":"Ada","github":"ada-dev"}"""
author = JSON.parse(json_text, Author)
println(author.name) # AdaTyped parsing is a good fit for application code, API clients, and any path where you want predictable fields instead of untyped containers.
Large files: lazy parsing
For very large documents, you do not always want to materialize the whole tree at once. JSON.lazy and JSON.lazyfile let you walk the document and materialize only the pieces you touch.
doc = JSON.lazyfile("events.json")
# Access only what you need
first_id = doc.events[1].id[]
println(first_id)This is especially useful when you only need a few fields from a huge export or API dump.
Reading JSON Files and JSON Lines
Use JSON.parsefile when the data already lives on disk. It supports the same options as JSON.parse, and it also understands JSON Lines files based on the filename extension.
config = JSON.parsefile("config.json"; dicttype=Dict)
# .jsonl and .ndjson are treated as JSON Lines by default
rows = JSON.parsefile("events.jsonl")
# Use missing instead of nothing if that fits your pipeline better
table_like = JSON.parsefile("report.json"; null=missing)Setting null=missing is a practical choice if the parsed result is headed into table-oriented Julia code where missing is more natural than nothing.
Formatting Julia Values as JSON
Converting Julia data back into JSON is straightforward with JSON.json. Use compact output for transport and pretty output for logs, fixtures, config files, or debugging.
Compact and pretty output
payload = Dict(
"tool" => "json-formatter",
"count" => 3,
"tags" => ["julia", "json"],
"notes" => nothing
)
compact = JSON.json(payload)
pretty = JSON.json(payload; pretty=2)
pretty_without_nulls = JSON.json(payload; pretty=2, omit_null=true)
println(compact)
println(pretty)
println(pretty_without_nulls)omit_null=true is useful when you want cleaner API payloads or config files without explicit null fields.
Writing straight to a file
You can write via an IO handle with JSON.print, or write directly by passing a file path to JSON.json.
JSON.json("output.json", payload; pretty=2)
open("compact.json", "w") do io
JSON.print(io, payload)
endFormatting your own types
If Julia does not know how to serialize a custom type, define JSON.lower so the object becomes a JSON-friendly structure first.
struct Location
city::String
country::String
end
JSON.lower(x::Location) = Dict(
"city" => x.city,
"country" => x.country,
)
println(JSON.json(Location("Vilnius", "Lithuania")))Common Julia JSON Pitfalls
- Old tutorials may be stale: if a guide says
JSON.parsereturns a plainDictby default, it is describing older behavior. nothingis notmissing: JSONnullmaps tonothingunless you explicitly choosenull=missing.- NaN and Infinity are not valid JSON:
JSON.jlcan allow them withallownan=true, but only use that for systems that intentionally accept non-standard JSON. - Trailing commas and single quotes still fail: if a payload came from hand-edited config, validate it before assuming the parser is wrong.
- Large repeated lookups can be slow on
JSON.Object: usedicttype=Dictwhen you need hash-based lookup behavior.
Practical Recommendation
For most Julia JSON work in 2026, start with JSON.jl, parse into regular Julia containers or your own structs, and switch on options like dicttype, null=missing, or lazy parsing only when the payload or workload justifies it. That keeps your code simple while still covering large files, typed application models, and human-readable formatting.
Need help with your JSON?
Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool