edn: olympos.io/encoding/edn Index | Examples | Files

package edn

import "olympos.io/encoding/edn"

Package edn implements encoding and decoding of EDN values as defined in https://github.com/edn-format/edn. For a full introduction on how to use go-edn, see https://github.com/go-edn/edn/blob/v1/docs/introduction.md. Fully self-contained examples of go-edn can be found at https://github.com/go-edn/edn/tree/v1/examples.

Note that the small examples in this package is not checking errors as persively as you should do when you use this package. This is done because I'd like the examples to be easily readable and understandable. The bigger examples provide proper error handling.

EDN, in contrast to JSON, supports arbitrary values as keys.

Code:

package main

import (
    "fmt"

    "olympos.io/encoding/edn"
)

type Point3 struct {
    X, Y, Z int64
}

type Unit struct {
    Type edn.Keyword
    HP   int
}

// EDN, in contrast to JSON, supports arbitrary values as keys.
func main() {
    input := `{{:x 1 :y 2 :z 3}    "Greybeard"
             {:y 10 :x 1 :z -10} "Blackwind"}`

    var locStarships map[Point3]string
    err := edn.UnmarshalString(input, &locStarships)
    if err != nil {
        panic(err)
    }

    p := Point3{1, 10, -10}

    fmt.Printf("Starship at location %v is %s\n", p, locStarships[p])

    input = `{[0 2]   {:type :scout :hp 55}
            [-3 10] {:type :villager :hp 25}
            [5 5]   {:type :bowman :hp 32}
            [5 6]   {:type :bowman :hp 29}}`

    var locUnits map[[2]int]Unit
    err = edn.UnmarshalString(input, &locUnits)
    if err != nil {
        panic(err)
    }

    loc := [2]int{5, 5}

    fmt.Printf("Unit at location %v is %+v\n", loc, locUnits[loc])

}

This example shows how one can implement enums and sets, and how to support multiple different forms for a specific value type. The set implemented here supports the notation `:all` for all values.

Code:

package main

import (
    "fmt"

    "olympos.io/encoding/edn"
)

type UserOption edn.Keyword

type UnknownUserOptionError UserOption

func (err UnknownUserOptionError) Error() string {
    return fmt.Sprintf("Unknown user option %s", edn.Keyword(err))
}

const (
    UnknownOption = UserOption("")
    ShowEmail     = UserOption("show-email")
    Notifications = UserOption("notifications")
    DailyEmail    = UserOption("daily-email")
    RememberMe    = UserOption("remember-me")
)

func ListUserOptions() []UserOption {
    return []UserOption{
        ShowEmail,
        Notifications,
        DailyEmail,
        RememberMe,
    }
}

func (uo *UserOption) UnmarshalEDN(bs []byte) error {
    var kw edn.Keyword
    err := edn.Unmarshal(bs, &kw)
    if err != nil {
        return err
    }
    opt := UserOption(kw)
    switch opt {
    case ShowEmail, Notifications, DailyEmail, RememberMe:
        *uo = opt
        return nil
    default:
        return UnknownUserOptionError(opt)
    }
}

type UserOptions map[UserOption]bool

func (opts *UserOptions) UnmarshalEDN(bs []byte) error {
    var kw edn.Keyword
    // try to decode into keyword first
    err := edn.Unmarshal(bs, &kw)
    if err == nil && kw == edn.Keyword("all") {
        // Put all options into the user option map
        *opts = UserOptions(make(map[UserOption]bool))
        for _, opt := range ListUserOptions() {
            (*opts)[opt] = true
        }
        return nil
    }
    // then try to decode into user map
    var rawOpts map[UserOption]bool
    err = edn.Unmarshal(bs, &rawOpts)
    *opts = UserOptions(rawOpts)
    return err
}

// This example shows how one can implement enums and sets, and how to support
// multiple different forms for a specific value type. The set implemented here
// supports the notation `:all` for all values.
func main() {
    inputs := []string{
        "#{:show-email :notifications}",
        "#{:notifications :show-email :remember-me}",
        ":all",
        "#{:doot-doot}",
        ":none",
        "#{} ;; no options",
    }
    for _, input := range inputs {
        var opts UserOptions
        err := edn.UnmarshalString(input, &opts)
        if err != nil {
            fmt.Println(err)
            // Do proper error handling here if something fails
            continue
        }
        // Cannot print out a map, as its ordering is nondeterministic.
        fmt.Printf("show email? %t, notifications? %t, daily email? %t, remember me? %t\n",
            opts[ShowEmail], opts[Notifications], opts[DailyEmail], opts[RememberMe])
    }

}

This example shows how to read and write basic EDN tags, and how this can be utilised: In contrast to encoding/json, you can read in data where you only know that the input satisfies some sort of interface, provided the value is tagged.

Code:

package main

import (
    "fmt"
    "strings"

    "olympos.io/encoding/edn"
)

type Notifiable interface {
    Notify()
}

type User struct {
    Username string
}

func (u User) MarshalEDN() ([]byte, error) {
    return edn.Marshal(edn.Tag{"myapp/user", u.Username})
}

func (u *User) Notify() {
    fmt.Printf("Notified user %s.\n", u.Username)
}

type Group struct {
    GroupID int
}

func (g Group) MarshalEDN() ([]byte, error) {
    return edn.Marshal(edn.Tag{"myapp/group", g.GroupID})
}

func (g *Group) Notify() {
    fmt.Printf("Notified group with id %d.\n", g.GroupID)
}

var notifyTagMap edn.TagMap

// We use a tagMap to avoid adding these values to the entire system.
func init() {
    err := notifyTagMap.AddTagFn("myapp/user", func(s string) (*User, error) {
        return &User{s}, nil
    })
    if err != nil {
        panic(err)
    }

    err = notifyTagMap.AddTagFn("myapp/group", func(id int) (*Group, error) {
        return &Group{id}, nil
    })
    if err != nil {
        panic(err)
    }
}

// This example shows how to read and write basic EDN tags, and how this can be
// utilised: In contrast to encoding/json, you can read in data where you only
// know that the input satisfies some sort of interface, provided the value is
// tagged.
func main() {
    input := `[#myapp/user "eugeness"
             #myapp/group 10
             #myapp/user "jeannikl"
             #myapp/user "jeremiah"
             #myapp/group 100]`

    rdr := strings.NewReader(input)
    dec := edn.NewDecoder(rdr)
    dec.UseTagMap(&notifyTagMap)

    var toNotify []Notifiable
    err := dec.Decode(&toNotify)
    if err != nil {
        panic(err)
    }
    for _, notify := range toNotify {
        notify.Notify()
    }

    // Print out the values as well
    out, err := edn.Marshal(toNotify)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(out))
}

This example shows how one can do streaming with the decoder, and how to properly know when the stream has no elements left.

Code:

package main

import (
    "fmt"
    "io"
    "strings"

    "olympos.io/encoding/edn"
)

// Typically, you'd also include timestamps here. Imagine that they are here.
type LogEntry struct {
    Level       edn.Keyword
    Message     string `edn:"msg"`
    Environment string `edn:"env"`
    Service     string
}

// This example shows how one can do streaming with the decoder, and how to
// properly know when the stream has no elements left.
func main() {
    const input = `
{:level :debug :msg "1 < 2 ? true" :env "dev" :service "comparer"}
{:level :warn :msg "slow response time from 127.0.1.39" :env "prod" :service "worker 10"}
{:level :warn :msg "worker 8 has been unavailable for 30s" :env "prod" :service "gateway"}
{:level :info :msg "new processing request: what.png" :env "prod" :service "gateway"}
{:level :debug :msg "1 < nil? error" :env "dev" :service "comparer"}
{:level :warn :msg "comparison failed: 1 < nil" :env "dev" :service "comparer"}
{:level :info :msg "received new processing request: what.png" :env "prod" :service "worker 3"}
{:level :warn :msg "bad configuration value :timeout, using 3h" :env "staging" :service "worker 3"}
`

    rdr := strings.NewReader(input)
    dec := edn.NewDecoder(rdr)
    var err error
    for {
        var entry LogEntry
        err = dec.Decode(&entry)
        if err != nil {
            break
        }
        if entry.Level == edn.Keyword("warn") && entry.Environment != "dev" {
            fmt.Println(entry.Message)
        }
    }
    if err != nil && err != io.EOF {
        // Something bad happened to our reader
        fmt.Println(err)
        return
    }
    // If err == io.EOF then we've reached end of stream
    fmt.Println("End of stream!")
}

Index

Examples

Package Files

compact.go decode.go edn_tags.go encode.go extras.go fold.go lexer.go pprint.go tags.go types.go

Variables

var (
    ErrNotFunc         = errors.New("Value is not a function")
    ErrMismatchArities = errors.New("Function does not have single argument in, two argument out")
    ErrNotConcrete     = errors.New("Value is not a concrete non-function type")
    ErrTagOverwritten  = errors.New("Previous tag implementation was overwritten")
)
var GlobalMathContext = MathContext{
    Mode:      big.ToNearestEven,
    Precision: 192,
}

The GlobalMathContext is the global MathContext. It is used if no other context is provided. See MathContext for example usage.

func AddTagFn Uses

func AddTagFn(tagname string, fn interface{}) error

AddTagFn adds fn as a converter function for tagname tags to the global TagMap. fn must have the signature func(T) (U, error), where T is the expected input type and U is the output type. See Decoder.AddTagFn for examples.

func AddTagStruct Uses

func AddTagStruct(tagname string, val interface{}) error

AddTagStructs adds the struct as a matching struct for tagname tags to the global TagMap. val can not be a channel, function, interface or an unsafe pointer. See Decoder.AddTagStruct for examples.

func Compact Uses

func Compact(dst *bytes.Buffer, src []byte) error

Compact appends to dst a compacted form of the EDN-encoded src. It does not remove discard values.

func Indent Uses

func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error

Indent writes to dst an indented form of the EDN-encoded src. Each EDN collection begins on a new, indented line beginning with prefix followed by one or more copies of indent according to the indentation nesting. The data written to dst does not begin with the prefix nor any indentation, and has no trailing newline, to make it easier to embed inside other formatted EDN data.

Indent filters away whitespace, including comments and discards.

func IndentStream Uses

func IndentStream(dst io.Writer, src io.Reader, prefix, indent string) error

IndentStream is an implementation of PPrint for generic readers and writers

func Marshal Uses

func Marshal(v interface{}) ([]byte, error)

Marshal returns the EDN encoding of v.

Marshal traverses the value v recursively. If an encountered value implements the Marshaler interface and is not a nil pointer, Marshal calls its MarshalEDN method to produce EDN. The nil pointer exception is not strictly necessary but mimics a similar, necessary exception in the behavior of UnmarshalEDN.

Otherwise, Marshal uses the following type-dependent default encodings:

Boolean values encode as EDN booleans.

Integers encode as EDN integers.

Floating point values encode as EDN floats.

String values encode as EDN strings coerced to valid UTF-8, replacing invalid bytes with the Unicode replacement rune. The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e" to keep some browsers from misinterpreting EDN output as HTML. Ampersand "&" is also escaped to "\u0026" for the same reason.

Array and slice values encode as EDN arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the nil EDN value.

Struct values encode as EDN maps. Each exported struct field becomes a member of the map unless

- the field's tag is "-", or
- the field is empty and its tag specifies the "omitempty" option.

The empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero. The map's default key is the struct field name as a keyword, but can be specified in the struct field's tag value. The "edn" key in the struct field's tag value is the key name, followed by an optional comma and options. Examples:

// Field is ignored by this package.
Field int `edn:"-"`

// Field appears in EDN as key :my-name.
Field int `edn:"myName"`

// Field appears in EDN as key :my-name and
// the field is omitted from the object if its value is empty,
// as defined above.
Field int `edn:"my-name,omitempty"`

// Field appears in EDN as key :field (the default), but
// the field is skipped if empty.
// Note the leading comma.
Field int `edn:",omitempty"`

The "str", "key" and "sym" options signals that a field name should be written as a string, keyword or symbol, respectively. If none are specified, then the default behaviour is to emit them as keywords. Examples:

// Default behaviour: field name will be encoded as :foo
Foo int

// Encode Foo as string with name "string-foo"
Foo int `edn:"string-foo,str"`

// Encode Foo as symbol with name sym-foo
Foo int `edn:"sym-foo,sym"`

Anonymous struct fields are usually marshaled as if their inner exported fields were fields in the outer struct, subject to the usual Go visibility rules amended as described in the next paragraph. An anonymous struct field with a name given in its EDN tag is treated as having that name, rather than being anonymous. An anonymous struct field of interface type is treated the same as having that type as its name, rather than being anonymous.

The Go visibility rules for struct fields are amended for EDN when deciding which field to marshal or unmarshal. If there are multiple fields at the same level, and that level is the least nested (and would therefore be the nesting level selected by the usual Go rules), the following extra rules apply:

1) Of those fields, if any are EDN-tagged, only tagged fields are considered, even if there are multiple untagged fields that would otherwise conflict. 2) If there is exactly one field (tagged or not according to the first rule), that is selected. 3) Otherwise there are multiple fields, and all are ignored; no error occurs.

To force ignoring of an anonymous struct field in both current and earlier versions, give the field a EDN tag of "-".

Map values usually encode as EDN maps. There are no limitations on the keys or values -- as long as they can be encoded to EDN, anything goes. Map values will be encoded as sets if their value type is either a bool or a struct with no fields.

If you want to ensure that a value is encoded as a map, you can specify that as follows:

// Encode Foo as a map, instead of the default set
Foo map[int]bool `edn:",map"`

Arrays and slices are encoded as vectors by default. As with maps and sets, you can specify that a field should be encoded as a list instead, by using the option "list":

// Encode Foo as a list, instead of the default vector
Foo []int `edn:",list"`

Pointer values encode as the value pointed to. A nil pointer encodes as the nil EDN object.

Interface values encode as the value contained in the interface. A nil interface value encodes as the nil EDN value.

Channel, complex, and function values cannot be encoded in EDN. Attempting to encode such a value causes Marshal to return an UnsupportedTypeError.

EDN cannot represent cyclic data structures and Marshal does not handle them. Passing cyclic structures to Marshal will result in an infinite recursion.

Code:

// values of type map[T]bool and map[T]struct{} are encoded as EDN sets by
// default
val := map[int]bool{42: true}

bs, _ := edn.Marshal(val)
fmt.Println(string(bs)) // => #{42}

val2 := map[string]struct{}{"hiccup": {}}
bs, _ = edn.Marshal(val2)
fmt.Println(string(bs)) // => #{"hiccup"}

Output:

#{42}
#{"hiccup"}

Code:

// You can specify that map[T]bool/struct{} are printed as EDN maps by using
// the `map` keyword in the EDN struct tag:
type Value struct {
    BoolMap   map[int]bool        `edn:"bool-map,map,omitempty"`
    StructMap map[string]struct{} `edn:"struct-map,map,omitempty"`
}

var val Value
val.BoolMap = map[int]bool{2: false}
bs, _ := edn.Marshal(val)
fmt.Println(string(bs)) // => {:bool-map{2 false}}

val.BoolMap = nil
val.StructMap = map[string]struct{}{"foo": {}}
bs, _ = edn.Marshal(val)
fmt.Println(string(bs)) // =>  {:struct-map{"foo"{}}}

Output:

{:bool-map{2 false}}
{:struct-map{"foo"{}}}

func MarshalIndent Uses

func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)

MarshalIndent is like Marshal but applies Indent to format the output.

func MarshalPPrint Uses

func MarshalPPrint(v interface{}, opts *PPrintOpts) ([]byte, error)

MarshalPPrint is like Marshal but applies PPrint to format the output.

func PPrint Uses

func PPrint(dst *bytes.Buffer, src []byte, opt *PPrintOpts) error

PPrint writes to dst an indented form of the EDN-encoded src. This implementation attempts to write idiomatic/readable EDN values, in a fashion close to (but not quite equal to) clojure.pprint/pprint.

PPrint filters away whitespace, including comments and discards.

func PPrintStream Uses

func PPrintStream(dst io.Writer, src io.Reader, opt *PPrintOpts) error

PPrintStream is an implementation of PPrint for generic readers and writers

func Unmarshal Uses

func Unmarshal(data []byte, v interface{}) error

Unmarshal parses the EDN-encoded data and stores the result in the value pointed to by v.

Unmarshal uses the inverse of the encodings that Marshal uses, allocating maps, slices, and pointers as necessary, with the following additional rules:

First, if the value to store the result into implements edn.Unmarshaler, it is called.

If the value is tagged and the tag is known, the EDN value is translated into the input of the tag convert function. If no error happens during converting, the result of the conversion is then coerced into v if possible.

To unmarshal EDN into a pointer, Unmarshal first handles the case of the EDN being the EDN literal nil. In that case, Unmarshal sets the pointer to nil. Otherwise, Unmarshal unmarshals the EDN into the value pointed at by the pointer. If the pointer is nil, Unmarshal allocates a new value for it to point to.

To unmarshal EDN into a struct, Unmarshal matches incoming object keys to the keys used by Marshal (either the struct field name or its tag), preferring an exact match but also accepting a case-insensitive match.

To unmarshal EDN into an interface value, Unmarshal stores one of these in the interface value:

bool, for EDN booleans
float64, for EDN floats
int64, for EDN integers
int32, for EDN characters
string, for EDN strings
[]interface{}, for EDN vectors and lists
map[interface{}]interface{}, for EDN maps
map[interface{}]bool, for EDN sets
nil for EDN nil
edn.Tag for unknown EDN tagged elements
T for known EDN tagged elements, where T is the result of the converter function

To unmarshal an EDN vector/list into a slice, Unmarshal resets the slice to nil and then appends each element to the slice.

To unmarshal an EDN map into a Go map, Unmarshal replaces the map with an empty map and then adds key-value pairs from the object to the map.

If a EDN value is not appropriate for a given target type, or if a EDN number overflows the target type, Unmarshal skips that field and completes the unmarshalling as best it can. If no more serious errors are encountered, Unmarshal returns an UnmarshalTypeError describing the earliest such error.

The EDN nil value unmarshals into an interface, map, pointer, or slice by setting that Go value to nil.

When unmarshaling strings, invalid UTF-8 or invalid UTF-16 surrogate pairs are not treated as an error. Instead, they are replaced by the Unicode replacement character U+FFFD.

Code:

// map[T]bool is considered as sets as well as maps
var val map[int]bool

edn.UnmarshalString("#{1 -5 42}", &val)
fmt.Println(val[42], val[123]) // => true false

edn.UnmarshalString("{1 false 2 true}", &val)
fmt.Println(val[1], val[2]) // => false true

Output:

true false
false true

func UnmarshalString Uses

func UnmarshalString(data string, v interface{}) error

UnmarshalString works like Unmarshal, but accepts a string as input instead of a byte slice.

func UseJSONAsFallback Uses

func UseJSONAsFallback(val bool)

UseJSONAsFallback can be set to true to let go-edn parse structs with information from the `json` tag for encoding and decoding type fields if not the `edn` tag field is set. This is not threadsafe: Encoding and decoding happening while this is called may return results that mix json and non-json tag reading. Preferably you call this in an init() function to ensure it is either set or unset.

type Decoder Uses

type Decoder struct {
    // contains filtered or unexported fields
}

A Decoder reads and decodes EDN objects from an input stream.

func NewDecoder Uses

func NewDecoder(r io.Reader) *Decoder

NewDecoder returns a new decoder that reads from r.

The decoder introduces its own buffering and may read data from r beyond the EDN values requested.

func (*Decoder) AddTagFn Uses

func (d *Decoder) AddTagFn(tagname string, fn interface{}) error

AddTagFn adds a tag function to the decoder's TagMap. Note that TagMaps are mutable: If Decoder A and B share TagMap, then adding a tag function to one may modify both.

Code:

input := `#complex [14.5 15.5]`

rdr := strings.NewReader(input)
dec := edn.NewDecoder(rdr)

intoComplex := func(v [2]float64) (complex128, error) {
    return complex(v[0], v[1]), nil
}
err := dec.AddTagFn("complex", intoComplex)
if err != nil {
    panic(err)
}

var cmplx complex128
err = dec.Decode(&cmplx)
if err != nil {
    panic(err)
}
fmt.Println(cmplx)

Output:

(14.5+15.5i)

Code:

input := `#com.myapp/duration "2h30m"`

rdr := strings.NewReader(input)
dec := edn.NewDecoder(rdr)
dec.AddTagFn("com.myapp/duration", time.ParseDuration)

var d time.Duration
dec.Decode(&d)
fmt.Println(d)

input = `#com.myapp/duration "1moment"`
rdr = strings.NewReader(input)
dec = edn.NewDecoder(rdr)
dec.AddTagFn("com.myapp/duration", time.ParseDuration)
err := dec.Decode(&d)
if err != nil {
    fmt.Println(err)
}

Output:

2h30m0s
time: unknown unit moment in duration 1moment

func (*Decoder) AddTagStruct Uses

func (d *Decoder) AddTagStruct(tagname string, example interface{}) error

AddTagStruct adds a tag struct to the decoder's TagMap. Note that TagMaps are mutable: If Decoder A and B share TagMap, then adding a tag struct to one may modify both.

Code:

// We can insert things into interfaces with tagged literals.
// Let's assume we have
// type Length interface { ToMetres() float64 }
// and Foot, Yard and Metre which satisfy the Length interface

input := `[#foot 14.5, #yard 2, #metre 3.0]`
rdr := strings.NewReader(input)
dec := edn.NewDecoder(rdr)
dec.AddTagStruct("foot", Foot(0))
dec.AddTagStruct("yard", Yard(0))
dec.AddTagStruct("metre", Metre(0))

var lengths []Length
dec.Decode(&lengths)
for _, len := range lengths {
    fmt.Printf("%.2f\n", len.ToMetres())
}

Output:

4.42
1.83
3.00

Code:

// Tag structs and tag functions can nest arbitrarily.
type Node struct {
    Left  *Node
    Val   int
    Right *Node
}

// function for finding the total sum of a tree
var sumTree func(n Node) int
sumTree = func(root Node) (val int) {
    if root.Left != nil {
        val += sumTree(*root.Left)
    }
    val += root.Val
    if root.Right != nil {
        val += sumTree(*root.Right)
    }
    return
}

input := `#node {:left #node {:val 1}
               :val 2
               :right #node {:left #node {:val 5}
                             :val 8
                             :right #node {:val 12}}}`
rdr := strings.NewReader(input)
dec := edn.NewDecoder(rdr)
dec.AddTagStruct("node", Node{})
var node Node
dec.Decode(&node)
fmt.Println(sumTree(node))

Output:

28

func (*Decoder) Buffered Uses

func (d *Decoder) Buffered() *bufio.Reader

Buffered returns a reader of the data remaining in the Decoder's buffer. The reader is valid until the next call to Decode.

func (*Decoder) Decode Uses

func (d *Decoder) Decode(val interface{}) (err error)

Decode reads the next EDN-encoded value from its input and stores it in the value pointed to by v.

See the documentation for Unmarshal for details about the conversion of EDN into a Go value.

func (*Decoder) UseMathContext Uses

func (d *Decoder) UseMathContext(mc MathContext)

UseMathContext sets the given math context as default math context for this decoder.

Code:

input := "3.14159265358979323846264338327950288419716939937510M"

rdr := strings.NewReader(input)
dec := edn.NewDecoder(rdr)

mathContext := edn.GlobalMathContext
// use global math context (does nothing)
dec.UseMathContext(mathContext)

var val *big.Float
dec.Decode(&val)
fmt.Printf("%.50f\n", val)

// reread with smaller precision and rounding towards zero
rdr = strings.NewReader(input)
dec = edn.NewDecoder(rdr)

mathContext.Precision = 30
mathContext.Mode = big.ToZero
dec.UseMathContext(mathContext)

dec.Decode(&val)
fmt.Printf("%.50f\n", val)

Output:

3.14159265358979323846264338327950288419716939937510
3.14159265160560607910156250000000000000000000000000

func (*Decoder) UseTagMap Uses

func (d *Decoder) UseTagMap(tm *TagMap)

UseTagMap sets the TagMap provided as the TagMap for this decoder.

type Encoder Uses

type Encoder struct {
    // contains filtered or unexported fields
}

An Encoder writes EDN values to an output stream.

func NewEncoder Uses

func NewEncoder(w io.Writer) *Encoder

NewEncoder returns a new encoder that writes to w.

func (*Encoder) Encode Uses

func (e *Encoder) Encode(v interface{}) error

Encode writes the EDN encoding of v to the stream, followed by a newline character.

See the documentation for Marshal for details about the conversion of Go values to EDN.

func (*Encoder) EncodeIndent Uses

func (e *Encoder) EncodeIndent(v interface{}, prefix, indent string) error

EncodeIndent writes the indented EDN encoding of v to the stream, followed by a newline character.

See the documentation for MarshalIndent for details about the conversion of Go values to EDN.

func (*Encoder) EncodePPrint Uses

func (e *Encoder) EncodePPrint(v interface{}, opts *PPrintOpts) error

EncodePPrint writes the pretty-printed EDN encoding of v to the stream, followed by a newline character.

See the documentation for MarshalPPrint for details about the conversion of Go values to EDN.

type InvalidUnmarshalError Uses

type InvalidUnmarshalError struct {
    Type reflect.Type
}

An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. (The argument to Unmarshal must be a non-nil pointer.)

func (*InvalidUnmarshalError) Error Uses

func (e *InvalidUnmarshalError) Error() string

type Keyword Uses

type Keyword string

A Keyword is an EDN keyword without : prepended in front.

Code:

const Friday = edn.Keyword("friday")
fmt.Println(Friday)

input := `:friday`
var weekday edn.Keyword
edn.UnmarshalString(input, &weekday)

if weekday == Friday {
    fmt.Println("It is friday!")
}

Output:

:friday
It is friday!

func (Keyword) MarshalEDN Uses

func (k Keyword) MarshalEDN() ([]byte, error)

func (Keyword) String Uses

func (k Keyword) String() string

type Marshaler Uses

type Marshaler interface {
    MarshalEDN() ([]byte, error)
}

Marshaler is the interface implemented by objects that can marshal themselves into valid EDN.

type MarshalerError Uses

type MarshalerError struct {
    Type reflect.Type
    Err  error
}

A MarshalerError is returned by Marshal when encoding a type with a MarshalEDN function fails.

func (*MarshalerError) Error Uses

func (e *MarshalerError) Error() string

type MathContext Uses

type MathContext struct {
    Precision uint
    Mode      big.RoundingMode
}

A MathContext specifies the precision and rounding mode for `math/big.Float`s when decoding.

Code:

input := "1.12345678901234567890123456789012345678901234567890M"
var val *big.Float
edn.UnmarshalString(input, &val)
fmt.Printf("%.50f\n", val)

// override default precision
mathContext := edn.GlobalMathContext
edn.GlobalMathContext.Precision = 30
edn.UnmarshalString(input, &val)
fmt.Printf("%.50f\n", val)

// revert it back to original values
edn.GlobalMathContext = mathContext

Output:

1.12345678901234567890123456789012345678901234567890
1.12345678918063640594482421875000000000000000000000

type PPrintOpts Uses

type PPrintOpts struct {
    RightMargin int
    MiserWidth  int
}

PPrintOpts is a configuration map for PPrint. The values in this struct has no effect as of now.

type RawMessage Uses

type RawMessage []byte

RawMessage is a raw encoded, but valid, EDN value. It implements Marshaler and Unmarshaler and can be used to delay EDN decoding or precompute an EDN encoding.

func (RawMessage) MarshalEDN Uses

func (m RawMessage) MarshalEDN() ([]byte, error)

MarshalEDN returns m as the EDN encoding of m.

func (*RawMessage) UnmarshalEDN Uses

func (m *RawMessage) UnmarshalEDN(data []byte) error

UnmarshalEDN sets *m to a copy of data.

type Rune Uses

type Rune rune

A Rune type is a wrapper for a rune. It can be used to encode runes as characters instead of int32 values.

Code:

runeSlice := []edn.Rune{'a', 'b', 'c', ',', ' ', '\n'}

bs, _ := edn.Marshal(runeSlice)

fmt.Println(string(bs))

Output:

[\a \b \c \u002c \space \newline]

func (Rune) MarshalEDN Uses

func (r Rune) MarshalEDN() ([]byte, error)

type Symbol Uses

type Symbol string

A Symbol is an EDN symbol.

func (Symbol) MarshalEDN Uses

func (s Symbol) MarshalEDN() ([]byte, error)

func (Symbol) String Uses

func (s Symbol) String() string

type SyntaxError Uses

type SyntaxError struct {
    Offset int64 // error occurred after reading Offset bytes
    // contains filtered or unexported fields
}

A SyntaxError is a description of an EDN syntax error.

func (*SyntaxError) Error Uses

func (e *SyntaxError) Error() string

type Tag Uses

type Tag struct {
    Tagname string
    Value   interface{}
}

A Tag is a tagged value. The Tagname represents the name of the tag, and the Value is the value of the element.

Code:

input := "#unknown ???"

var tag edn.Tag
edn.UnmarshalString(input, &tag)

fmt.Printf("Tag with name %s and value %q of type %T\n", tag.Tagname, tag.Value, tag.Value)

Output:

Tag with name unknown and value "???" of type edn.Symbol

func (Tag) MarshalEDN Uses

func (t Tag) MarshalEDN() ([]byte, error)

func (Tag) String Uses

func (t Tag) String() string

func (*Tag) UnmarshalEDN Uses

func (t *Tag) UnmarshalEDN(bs []byte) error

type TagMap Uses

type TagMap struct {
    sync.RWMutex
    // contains filtered or unexported fields
}

A TagMap contains mappings from tag literals to functions and structs that is used when decoding.

func (*TagMap) AddTagFn Uses

func (tm *TagMap) AddTagFn(tagname string, fn interface{}) error

AddTagFn adds fn as a converter function for tagname tags to this TagMap. fn must have the signature func(T) (U, error), where T is the expected input type and U is the output type. See Decoder.AddTagFn for examples.

func (*TagMap) AddTagStruct Uses

func (tm *TagMap) AddTagStruct(tagname string, val interface{}) error

AddTagStructs adds the struct as a matching struct for tagname tags to this TagMap. val can not be a channel, function, interface or an unsafe pointer. See Decoder.AddTagStruct for examples.

type UnhashableError Uses

type UnhashableError struct {
    Position int64
}

UnhashableError is an error which occurs when the decoder attempted to assign an unhashable key to a map or set. The position close to where value was found is provided to help debugging.

func (*UnhashableError) Error Uses

func (e *UnhashableError) Error() string

type UnknownTagError Uses

type UnknownTagError struct {
    // contains filtered or unexported fields
}

func (UnknownTagError) Error Uses

func (ute UnknownTagError) Error() string

type UnmarshalTypeError Uses

type UnmarshalTypeError struct {
    Value string       // description of EDN value - "bool", "array", "number -5"
    Type  reflect.Type // type of Go value it could not be assigned to
}

An UnmarshalTypeError describes a EDN value that was not appropriate for a value of a specific Go type.

func (*UnmarshalTypeError) Error Uses

func (e *UnmarshalTypeError) Error() string

type Unmarshaler Uses

type Unmarshaler interface {
    UnmarshalEDN([]byte) error
}

Unmarshaler is the interface implemented by objects that can unmarshal an EDN description of themselves. The input can be assumed to be a valid encoding of an EDN value. UnmarshalEDN must copy the EDN data if it wishes to retain the data after returning.

type UnsupportedTypeError Uses

type UnsupportedTypeError struct {
    Type reflect.Type
}

An UnsupportedTypeError is returned by Marshal when attempting to encode an unsupported value type.

func (*UnsupportedTypeError) Error Uses

func (e *UnsupportedTypeError) Error() string

type UnsupportedValueError Uses

type UnsupportedValueError struct {
    Value reflect.Value
    Str   string
}

An UnsupportedValueError is returned by Marshal when attempting to encode an unsupported value. Examples include the float values NaN and Infinity.

func (*UnsupportedValueError) Error Uses

func (e *UnsupportedValueError) Error() string

Package edn imports 18 packages (graph) and is imported by 4 packages. Updated 2020-03-09. Refresh now. Tools for package owners.