https://github.com/pennocktech/swallowjson
Golang: Support for preserving unknown fields from JSON when unmarshalling instead of discarding
https://github.com/pennocktech/swallowjson
encoding golang json json-fields reflect swallow
Last synced: 3 months ago
JSON representation
Golang: Support for preserving unknown fields from JSON when unmarshalling instead of discarding
- Host: GitHub
- URL: https://github.com/pennocktech/swallowjson
- Owner: PennockTech
- License: mit
- Created: 2016-09-13T02:35:29.000Z (over 9 years ago)
- Default Branch: main
- Last Pushed: 2025-05-28T00:55:13.000Z (11 months ago)
- Last Synced: 2025-10-05T21:20:32.770Z (7 months ago)
- Topics: encoding, golang, json, json-fields, reflect, swallow
- Language: Go
- Size: 27.3 KB
- Stars: 5
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
swallowjson
===========
[](https://github.com/PennockTech/swallowjson/actions/workflows/pushes.yaml)
[](https://godoc.org/go.pennock.tech/swallowjson)
[](https://coveralls.io/github/PennockTech/swallowjson?branch=main)
The `swallowjson` Golang library provides a simple-to-use support function to
use to implement an interface method in your type, to aid in JSON decoding.
When decoding JSON into a struct, the default Golang handling is to discard
the JSON fields encountered which have not been declared as struct fields.
The `UnmarshalWith` function lets you implement the `UnmarshalJSON` method as
a one-liner, declaring a map within the struct which should swallow all JSON
fields not otherwise accepted by the struct.
A simple example:
```go
type MyType struct {
Foo string `json:"foo"`
Bar int `json:"bar"`
Rest map[string]interface{} `json:"-"`
}
func (mt *MyType) UnmarshalJSON(raw []byte) error {
return swallowjson.UnmarshalWith(mt, "Rest", raw)
}
```
You can then decode as normal for Golang, letting the JSON decoder dispatch to
your overridden `UnmarshalJSON` method whenever it expects to decode a
`MyType` (whether at the top-level, or nested inside other types, etc):
```go
var myData MyType
if err := json.Unmarshal(rawBytes, &myData); err != nil {
processError(err)
}
```
When invoked on `mt`, which should already exist as a struct,
`swallowjson.UnmarshalWith` will populate `Foo` and `Bar` from JSON fields
`foo` and `bar` respectively, per normal Golang decoding rules. But if the
JSON also contains fields `baz` and `bat` then those will end up as keys,
holding their child data, in the `Rest` map.
This library was written as a fairly quick proof-of-concept for a friend and
later gained sufficient tests as to be something which can be relied upon as a
core component, with no other dependencies.
The library is released in the hopes that it might prove useful to others.
Behavior notes:
* The Golang [encoding/json][] library has a bunch of legacy
case-insensitivity handling in the default unmarshaller; while swallowjson
builds upon that library (it uses `json.NewDecoder()` under the hood) our
API is a new API, implemented in new code and is not a drop-in replacement.
Thus there is no need to preserve backwards behavior here, so I didn't
implement that case-insensitivity.
* The `Rest` map will be created on-demand; if no unexpected keys are seen and
the map is `nil` going in, then it will still be `nil` afterwards.
* The `Rest` map can have arbitrary value types, but if the content won't
parse then you'll get an error. Sensible choices for generic usage include
`interface{}` and `json.RawMessage`.
Canonical import path is: `go.pennock.tech/swallowjson`
---
Copyright © 2016-2020 Pennock Tech, LLC
Licensed per [LICENSE.txt](./LICENSE.txt)
[encoding/json]: https://golang.org/pkg/encoding/json/