• Stars
    star
    312
  • Rank 134,133 (Top 3 %)
  • Language
    Julia
  • License
    Other
  • Created almost 12 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

JSON parsing and printing

JSON.jl

This package provides for parsing and printing JSON in pure Julia.

Build Status codecov.io

Installation

Type ] add JSON and then hit ⏎ Return at the REPL. You should see pkg> add JSON.

Basic Usage

import JSON

# JSON.parse - string or stream to Julia data structures
s = "{\"a_number\" : 5.0, \"an_array\" : [\"string\", 9]}"
j = JSON.parse(s)
#  Dict{AbstractString,Any} with 2 entries:
#    "an_array" => {"string",9}
#    "a_number" => 5.0

# JSON.json - Julia data structures to a string
JSON.json([2,3])
#  "[2,3]"
JSON.json(j)
#  "{\"an_array\":[\"string\",9],\"a_number\":5.0}"

Documentation

JSON.print(io::IO, s::AbstractString)
JSON.print(io::IO, s::Union{Integer, AbstractFloat})
JSON.print(io::IO, n::Nothing)
JSON.print(io::IO, b::Bool)
JSON.print(io::IO, a::AbstractDict)
JSON.print(io::IO, v::AbstractVector)
JSON.print(io::IO, v::Array)

Writes a compact (no extra whitespace or indentation) JSON representation to the supplied IO.

JSON.print(a::AbstractDict, indent)
JSON.print(io::IO, a::AbstractDict, indent)

Writes a JSON representation with newlines, and indentation if specified. Non-zero indent will be applied recursively to nested elements.

json(a::Any)

Returns a compact JSON representation as an AbstractString.

JSON.parse(s::AbstractString; dicttype=Dict, inttype=Int64)
JSON.parse(io::IO; dicttype=Dict, inttype=Int64)
JSON.parsefile(filename::AbstractString; dicttype=Dict, inttype=Int64, use_mmap=true)

Parses a JSON AbstractString or IO stream into a nested Array or Dict.

The dicttype indicates the dictionary type (<: Associative), or a function that returns an instance of a dictionary type, that JSON objects are parsed to. It defaults to Dict (the built-in Julia dictionary), but a different type can be passed for additional functionality. For example, if you import DataStructures (assuming the DataStructures package is installed)

  • you can pass dicttype=DataStructures.OrderedDict to maintain the insertion order of the items in the object;
  • or you can pass ()->DefaultDict{String,Any}(Missing) to having any non-found keys return missing when you index the result.

The inttype argument controls how integers are parsed. If a number in a JSON file is recognized to be an integer, it is parsed as one; otherwise it is parsed as a Float64. The inttype defaults to Int64, but, for example, if you know that your integer numbers are all small and want to save space, you can pass inttype=Int32. Alternatively, if your JSON input has integers which are too large for Int64, you can pass inttype=Int128 or inttype=BigInt. inttype can be any subtype of Real.

JSONText(s::AbstractString)

A wrapper around a Julia string representing JSON-formatted text, which is inserted as-is in the JSON output of JSON.print and JSON.json.

JSON.lower(p::Point2D) = [p.x, p.y]

Define a custom serialization rule for a particular data type. Must return a value that can be directly serialized; see help for more details.

Customizing JSON

Users may find the default behaviour of JSON inappropriate for their use case. In such cases, JSON provides two mechanisms for users to customize serialization. The first method, JSON.Writer.StructuralContext, is used to customize the cosmetic properties of the serialized JSON. (For example, the default pretty printing vs. compact printing is supported by provided two different StructuralContexts.) Examples of applications for which StructuralContext is appropriate include: particular formatting demands for JSON (maybe not in compliance with the JSON standard) or JSON-like formats with different syntax.

The second method, JSON.Serializations.Serialization, is used to control the translation of Julia objects into JSON serialization instructions. In most cases, writing a method for JSON.lower (as mentioned above) is sufficient to define JSON serializations for user-defined objects. However, this is not appropriate for overriding or deleting predefined serializations (since that would globally affect users of the JSON module and is an instance of dangerous type piracy). For these use-cases, users should define a custom instance of Serialization. An example of an application for this use case includes: a commonly requested extension to JSON which serializes float NaN and infinite values as NaN or Inf, in contravention of the JSON standard.

Both methods are controlled by the JSON.show_json function, which has the following signature:

JSON.show_json(io::StructuralContext, serialization::Serialization, object)

which is expected to write to io in a way appropriate based on the rules of Serialization, but here io is usually (but not required to be) handled in a higher-level manner than a raw IO object would ordinarily be.

StructuralContext

To define a new StructuralContext, the following boilerplate is recommended:

import JSON.Writer.StructuralContext
[mutable] struct MyContext <: StructuralContext
    io::IO
    [ ... additional state / settings for context goes here ... ]
end

If your structural context is going to be very similar to the existing JSON contexts, it is also possible to instead subtype the abstract subtype JSONContext of StructuralContext. If this is the case, an io::IO field (as above) is preferred, although the default implementation will only use this for write, so replacing that method is enough to avoid this requirement.

The following methods should be defined for your context, regardless of whether it subtypes JSONContext or StructuralContext directly. If some of these methods are omitted, then CommonSerialization cannot be generally used with this context.

# called when the next object in a vector or next pair of a dict is to be written
# (requiring a newline and indent for some contexts)
# can do nothing if the context need not support indenting
JSON.Writer.indent(io::MyContext)

# called for vectors/dicts to separate items, usually writes ","
# unless this is the first element in a JSON array
# (default implementation for JSONContext exists, but requires a mutable bool
#  `first` field, and this is an implementation detail not to be relied on; 
#  to define own or delegate explicitly)
JSON.Writer.delimit(io::MyContext)

# called for dicts to separate key and value, usually writes ": "
JSON.Writer.separate(io::MyContext)

# called to indicate start and end of a vector
JSON.Writer.begin_array(io::MyContext)
JSON.Writer.end_array(io::MyContext)

# called to indicate start and end of a dict
JSON.Writer.begin_object(io::MyContext)
JSON.Writer.end_object(io::MyContext)

For the following methods, JSONContext provides a default implementation, but it can be specialized. For StructuralContexts which are not JSONContexts, the JSONContext defaults are not appropriate and so are not available.

# directly write a specific byte (if supported)
# default implementation writes to underlying `.io` field
# note that this enables JSONContext to act as any `io::IO`,
# i.e. one can use `print`, `show`, etc.
Base.write(io::MyContext, byte::UInt8)

# write "null"
# default implementation writes to underlying `.io` field
JSON.Writer.show_null(io::MyContext)

# write an object or string in a manner safe for JSON string
# default implementation calls `print` but escapes each byte as appropriate
# and adds double quotes around the content of `elt`
JSON.Writer.show_string(io::MyContext, elt)

# write a new element of JSON array
# default implementation calls delimit, then indent, then show_json
JSON.Writer.show_element(io::MyContext, elt)

# write a key for a JSON object
# default implementation calls delimit, then indent, then show_string,
# then separate
JSON.Writer.show_key(io::MyContext, elt)

# write a key-value pair for a JSON object
# default implementation calls show key, then show_json
JSON.Writer.show_pair(io::MyContext, s::Serialization, key, value)

What follows is an example of a JSONContext subtype which is very similar to the default context, but which uses None instead of null for JSON nulls, which is then generally compatible with Python object literal notation (PYON). It wraps a default JSONContext to delegate all the required methods to. Since the wrapped context already has a .io, this object does not need to include an .io field, and so the write method must also be delegated, since the default is not appropriate. The only other specialization needed is show_null.

import JSON.Writer
import JSON.Writer.JSONContext
mutable struct PYONContext <: JSONContext
    underlying::JSONContext
end

for delegate in [:indent,
                 :delimit,
                 :separate,
                 :begin_array,
                 :end_array,
                 :begin_object,
                 :end_object]
    @eval JSON.Writer.$delegate(io::PYONContext) = JSON.Writer.$delegate(io.underlying)
end
Base.write(io::PYONContext, byte::UInt8) = write(io.underlying, byte)

JSON.Writer.show_null(io::PYONContext) = print(io, "None")
pyonprint(io::IO, obj) = let io = PYONContext(JSON.Writer.PrettyContext(io, 4))
    JSON.print(io, obj)
    return
end

The usage of this pyonprint function is as any other print function, e.g.

julia> pyonprint(stdout, [1, 2, nothing])
[
    1,
    2,
    None
]

julia> sprint(pyonprint, missing)
"None"

Serialization

For cases where the JSON cosmetics are unimportant, but how objects are converted into their JSON equivalents (arrays, objects, numbers, etc.) need to be changed, the appropriate abstraction is Serialization. A Serialization instance is used as the second argument in show_json. Thus, specializing show_json for custom Serialization instances enables either creating more restrictive or different ways to convert objects into JSON.

The default serialization is called JSON.Serializations.StandardSerialization, which is a subtype of CommonSerialization. Methods of show_json are not added to StandardSerialization, but rather to CommonSerialization, by both JSON and by other packages for their own types. The lower functionality is also specific to CommonSerialization. Therefore, to create a serialization instance that inherits from and may extend or override parts of the standard serialization, it suffices to define a new serialization subtyping CommonSerialization. In the example below, the new serialization is the same as StandardSerialization except that numbers are serialized with an additional type tag.

import JSON.Serializations: CommonSerialization, StandardSerialization
import JSON.Writer: StructuralContext, show_json
struct TaggedNumberSerialization <: CommonSerialization end

tag(f::Real) = Dict(:type => string(typeof(f)), :value => f)
show_json(io::StructuralContext,
            ::TaggedNumberSerialization,
           f::Union{Integer, AbstractFloat}) =
    show_json(io, StandardSerialization(), tag(f))

Note that the recursive call constructs a StandardSerialization(), as otherwise this would result in a stack overflow, and serializes a Dict using that. In this toy example, this is fine (with only the overhead of constructing a Dict), but this is not always possible. (For instance, if the constructed Dict could have other numbers within its values that need to be tagged.)

To deal with these more complex cases, or simply to eliminate the overhead of constructing the intermediate Dict, the show_json method can be implemented more carefully by explicitly calling the context’s begin_object, show_pair, and end_object methods, as documented above, and use the StandardSerialization() only for the show_pair call for f.

# More careful implementation
# No difference in this case, but could be needed if recursive data structures are to be
# serialized in more complex cases.
import JSON.Writer: begin_object, show_pair, end_object
function show_json(io::StructuralContext,
                    s::TaggedNumberSerialization,
                    f::Union{Integer, AbstractFloat})
    begin_object(io)
    show_pair(io, s, :tag => string(typeof(f)))
    show_pair(io, StandardSerialization(), :value => f)
    end_object(io)
end

To use the custom serialization, sprint can be used (and this can be encapsulated by a convenient user-defined interface):

julia> JSON.parse(sprint(show_json, TaggedNumberSerialization(), Any[1, 2.0, "hi"]))
3-element Array{Any,1}:
 Dict{String,Any}("value" => 1,"type" => "Int64")
 Dict{String,Any}("value" => 2.0,"type" => "Float64")
 "hi"

If it is not desired to inherit all the functionality of StandardSerialization, users may also choose to start from scratch by directly subtyping JSON.Serializations.Serialization. This is useful if the user wishes to enforce a strict JSON which throws errors when attempting to serialize objects that aren’t explicitly supported. Note that this means you will need to define a method to support serializing any kind of object, including the standard JSON objects like booleans, integers, strings, etc.!

More Repositories

1

JLD2.jl

HDF5-compatible file format in pure Julia
Julia
553
star
2

HDF5.jl

Save and load data in the HDF5 file format from Julia
Julia
390
star
3

MAT.jl

Julia module for reading MATLAB files
Julia
279
star
4

JLD.jl

Saving and loading julia variables while preserving native types
Julia
276
star
5

FileIO.jl

Main Package for IO, loading all different kind of files
Julia
217
star
6

ProtoBuf.jl

Julia protobuf implementation
Julia
205
star
7

BSON.jl

Julia
157
star
8

Formatting.jl

Deprecated. See README. (A Julia package to provide Python-like formatting support)
Julia
131
star
9

VideoIO.jl

Reading and writing of video files in Julia via ffmpeg
Julia
128
star
10

Suppressor.jl

Julia macros for suppressing and/or capturing output (STDOUT), warnings (STDERR) or both streams at the same time.
Julia
124
star
11

EzXML.jl

XML/HTML handling tools for primates
Julia
122
star
12

Zarr.jl

Julia
119
star
13

Parquet.jl

Julia implementation of Parquet columnar file format reader
Julia
116
star
14

LightXML.jl

A light-weight Julia package for XML based on libxml2.
Julia
91
star
15

TranscodingStreams.jl

Simple, consistent interfaces for any codec.
Julia
86
star
16

MeshIO.jl

IO for Meshes
Roff
79
star
17

Tar.jl

TAR files: create, list, extract them in pure Julia
Julia
79
star
18

MsgPack.jl

Julia MsgPack implementation with type-driven, overloadable packing/unpacking functionality
Julia
65
star
19

LibSerialPort.jl

Julia wrapper for the libserialport c library
Julia
65
star
20

ImageMagick.jl

Thin Wrapper for the library ImageMagick
Julia
53
star
21

CodecZlib.jl

zlib codecs for TranscodingStreams.jl.
Julia
52
star
22

ConfParser.jl

Julia package for parsing configuration files
Julia
43
star
23

BufferedStreams.jl

Fast composable IO streams
Julia
42
star
24

Sixel.jl

The Julia wrapper of libsixel
Julia
41
star
25

GZip.jl

A Julia interface for gzip functions in zlib
Julia
39
star
26

FFMPEG.jl

Julia Package for the FFMPEG builder binaries
Julia
34
star
27

SerialPorts.jl

SerialPort IO streams in Julia backed by pySerial.
Julia
31
star
28

Blosc.jl

Blosc compression for the Julia language
Julia
29
star
29

ImageIO.jl

Load images in Julia. Designed for FileIO interaction. Supports PNG and Portable Bitmap formats
Julia
28
star
30

GoogleDrive.jl

Automate Google-Drive download in Julia
Julia
24
star
31

MultifileArrays.jl

Create a higher-dimensional array from lazily-loaded slices in separate files
Julia
23
star
32

CodecZstd.jl

A zstd codec for TranscodingStreams.jl.
Julia
23
star
33

StructIO.jl

binary I/O methods generated from Julia structure definitions
Julia
22
star
34

Pcap.jl

libpcap implementation for Julia language
Julia
20
star
35

PNGFiles.jl

FileIO.jl integration for PNG files
Julia
20
star
36

CBOR.jl

A Concise Binary Object Representation (RFC 7049) serialization library in Julia
Julia
19
star
37

FileTypes.jl

Small and dependency-free Julia package to infer file and MIME type checking the magic numbers signature.
Julia
18
star
38

Snappy.jl

A fast compressor/decompressor
Julia
16
star
39

JpegTurbo.jl

Julia interface to libjpeg-turbo
Julia
15
star
40

ArgTools.jl

Tools for writing functions that handle many kinds of IO arguments
Julia
14
star
41

IniFile.jl

Reading and writing Windows-style INI files (writing not yet implemented).
Julia
14
star
42

ZipArchives.jl

Read and write Zip archive files in Julia.
Julia
13
star
43

HexEdit.jl

Julia package for editing and displaying binary file data in hexadecimal format
Julia
13
star
44

WidthLimitedIO.jl

A Julia IO type that facilitates width-limited printing
Julia
12
star
45

QuartzImageIO.jl

Exposes macOS's native image IO functionality to Julia
Julia
12
star
46

GIFImages.jl

Provides Gif support in Julia using LibGif
Julia
12
star
47

NRRD.jl

Julia support for the Nearly Raw Raster Data (NRRD) image file format
Julia
10
star
48

ZeissMicroscopyFormat.jl

Importing the Zeiss CZI file format for microscopy
Julia
9
star
49

LibExpat.jl

Julia interface to the Expat XML parser library
Julia
9
star
50

CodecLz4.jl

Transcoding codecs for compression and decompression with LZ4
Julia
9
star
51

FLAC.jl

Julia bindings for libFLAC
Julia
9
star
52

CodecBzip2.jl

A bzip2 codec for TranscodingStreams.jl.
Julia
8
star
53

ImgHdr.jl

Library to Check Type of Image
Julia
7
star
54

CodecXz.jl

An xz codec for TranscodingStreams.jl.
Julia
7
star
55

CodecBase.jl

Base 16/32/64 codecs for TranscodingStreams.jl
Julia
7
star
56

CRC32.jl

CRC32 package for Julia
Julia
6
star
57

Telegram.jl

wrapper for the Telegram API in Julia (https://github.com/vysheng/tgl)
Julia
6
star
58

Toxcore.jl

Toxcore wrapper
Julia
6
star
59

VideoPlayer.jl

Video player for Julia
Julia
6
star
60

BSDiff.jl

Pure Julia port of bsdiff
Julia
5
star
61

HDF5Plugins.jl

Compression plugins for HDF5.jl implemented in Julia
Julia
5
star
62

libserialport

A mirror of libserialport for the provision of Windows binaries through CI
C
5
star
63

MetaImageFormat.jl

Support for reading MetaImage files in Julia
Julia
4
star
64

AndorSIF.jl

Read Andor SIF file in Julia
Julia
4
star
65

AdjustCRC.jl

adjust the CRC32/32c checksum of data to any desired value
Julia
4
star
66

Netpbm.jl

Load and save Netpbm images in Julia
Julia
4
star
67

ImageMagickBuilder

binary deps for ImageMagick
Julia
3
star
68

Blosc2.jl

blosc2 wrapper for Julia lang
Julia
3
star
69

SigMF.jl

The Signal Metadata Format
Julia
3
star
70

AVSfldIO.jl

File IO for AVS .fld format data files
Julia
2
star
71

BSDiffTestData

Data for testing https://github.com/JuliaIO/BSDiff.jl
2
star
72

LibpngBuilder

Julia
2
star
73

FFMPEGBuilder

BinaryBuilder repo for FFMPEG
Julia
2
star
74

LibVPXBuilder

BinaryBuilder repo for LibVPX
Julia
2
star
75

x264Builder

BinaryBuilder repo for x264
Julia
2
star
76

YasmBuilder

BinaryBuilder repo for Yasm
Julia
2
star
77

LibJPEGBuilder

Julia
2
star
78

LibTIFFBuilder

Julia
2
star
79

LAMEBuilder

Julia
2
star
80

WavefrontObj.jl

Julia
2
star
81

nasmBuilder

Julia
2
star
82

LibVorbisBuilder

builder for libvorbis
Julia
2
star
83

JLDArchives.jl

A repository of Julia *.jld files for testing backwards compatibility
Julia
2
star
84

OggBuilder

BinaryBuilder repo for libogg
Julia
2
star
85

x265Builder

BinaryBuilder repo for x265
Julia
2
star
86

LibassBuilder

Julia
2
star
87

LibALSABuilder

BinaryBuilder repo for alsa-lib
Julia
2
star
88

InputBuffers.jl

A Julia package to wrap an AbstractVector{UInt8} in a readable seekable IO type.
Julia
2
star
89

Roadmap

Roadmap for the JuliaIO Organization
2
star
90

CodecInflate64.jl

Julia implementation of deflate64 decompression
Julia
1
star
91

Kerchunk.jl

Julia
1
star