Skip to content

Instantly share code, notes, and snippets.

@adlrocha
Created March 21, 2021 07:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adlrocha/28c522e0bb3e628d65531a84b5c7fb5e to your computer and use it in GitHub Desktop.
Save adlrocha/28c522e0bb3e628d65531a84b5c7fb5e to your computer and use it in GitHub Desktop.
/* Copyright (c) 2021, Alfonso de la Rocha
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
package main
import (
"fmt"
"encoding/json"
)
// Object Structs
type Node interface{
Print()
}
type Pair struct {
Key Node `json:"key"`
Value Node `json:"value"`
}
type Pairs []Pair
type String struct {
Value string
}
type Int struct {
Value int
}
func (s String) Print(){
fmt.Println(s.Value)
}
// MarshalType to strongly type json
type MarshalType int
const (
StringType = iota
IntType
)
func (i Int) Print(){
fmt.Println(i.Value)
}
// Custom Marshal Functions
func (s String) MarshalJSON() (bdata []byte, e error) {
// Temporal type to avoid recursion
type tmp String
ts := tmp(s)
c := struct {
Type MarshalType `json:"type"`
Value tmp `json:"value"`
}{Type: StringType, Value: ts}
return json.Marshal(&c)
}
func (i Int) MarshalJSON() (bdata []byte, e error) {
// Temporal type to avoid recursion
type tmp Int
ts := tmp(i)
c := struct {
Type MarshalType `json:"type"`
Value tmp `json:"value"`
}{Type: IntType, Value: ts}
return json.Marshal(&c)
}
// Unmarshaling Pair types
func UnmarshalType(tp MarshalType, b []byte) (Node, error) {
switch tp {
case StringType:
var n String
err := json.Unmarshal(b, &n)
if err != nil {
return nil, err
}
return n, nil
case IntType:
var n Int
err := json.Unmarshal(b, &n)
if err != nil {
return nil, err
}
return n, nil
}
return nil, fmt.Errorf("Wrong type")
}
// Custom unmarshal for pairs
func (p *Pair) UnmarshalJSON(b []byte) error {
var objMap map[string]map[string]*json.RawMessage
err := json.Unmarshal(b, &objMap)
if err != nil {
return err
}
var kType, vType int
json.Unmarshal(*objMap["key"]["type"], &kType)
json.Unmarshal(*objMap["value"]["type"], &vType)
p.Key, err = UnmarshalType(MarshalType(kType), *objMap["key"]["value"])
if err != nil {
return err
}
p.Value, err = UnmarshalType(MarshalType(vType), *objMap["value"]["value"])
if err != nil {
return err
}
return nil
}
func main() {
// Marshaling a struct
fmt.Println("== Marshalling struct ==")
p := Pair{Key: String{"someKey"}, Value: Int{1}}
// Marshal
byteData, err := json.Marshal(p)
checkErr(err)
fmt.Println("Marshalled:", string(byteData))
// Unmarshal into Pair struct
pout := Pair{}
err = json.Unmarshal(byteData, &pout)
fmt.Println("Unmarshalled:", pout)
// Marshaling a list of Pairs
fmt.Println("== Marshalling pairs ==")
p1 := Pair{Key: String{"someKey"}, Value: Int{1}}
p2 := Pair{Key: String{"otherKey"}, Value: Int{2}}
pl := Pairs{p1, p2}
byteData, err = json.Marshal(pl)
checkErr(err)
fmt.Println("Marshalled:", string(byteData))
// Unmarshalling into the right type
plout := Pairs{}
err = json.Unmarshal(byteData, &plout)
fmt.Println("Unmarshalled:", plout)
}
func checkErr(err error){
if err != nil{
panic(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment