I have a Type "Book" that i read from a different interface which returns json. After reading the json and processing data, i have to convert the book to a public book type to hide fields and change output format.
My problem is, that the input type from the same field (ISBN) is sometimes string and sometimes int. I thought that the easiest solution is to use json.Number to unmarshal the data. That works - but i need string on the outgoing json on different fields...
That is the point where i need help. I would have a custom type which i can set in the public structure at the fields, where i want to set the output-json-field to string. I named the custom type "mytype" in the example. (The real data are nested and i have more fields that i set to string in the output - the id field in the public structure is only a test)
I mean, it should look something like that - or not?
func (m *mytype) MarshalJSON() ([]byte, error) {
...
}
Here is my example code: https://play.golang.org/p/rS9HddzDMp
package main
import (
"encoding/json"
"fmt"
"bytes"
)
/* ----------------------------------------------------------------------------------------------------
Definition of the internal Book object (read from input)
-----------------------------------------------------------------------------------------------------*/
type Book struct {
Id json.Number `json:"id"`
Revision int `json:"revision"`
ISBN json.Number `json:"isbn"`
Title string `json:"title"`
}
/* ----------------------------------------------------------------------------------------------------
Definition of the public Book object
-----------------------------------------------------------------------------------------------------*/
type AliasBook Book
type omit *struct{}
type mytype string
type PublicBook struct {
Id string `json:"id"`
Revision omit `json:"revision,omitempty"`
ISBN mytype `json:"isbn"`
*AliasBook
}
/* ----------------------------------------------------------------------------------------------------
Rendering functions
-----------------------------------------------------------------------------------------------------*/
func (bb *Book) MarshalJSON() ([]byte, error) {
fmt.Println("---------------MarschalJSON---------------")
aux := PublicBook{
Id: bb.Id.String(),
AliasBook: (*AliasBook)(bb),
}
return json.Marshal(&aux)
}
func main() {
var jsonStreams[2][]byte
// Input ISBN as string
jsonStreams[0] = []byte(`{"id":"123","revision":1234,"isbn":"978-3-86680-192-9","title":"Go for dummies"}`)
// Input ISBN as int
jsonStreams[1] = []byte(`{"id":123,"revision":1234,"isbn":9783866801929,"title":"Go for dummies"}`)
// For each stream
for i := range jsonStreams {
fmt.Print("stream: ")
fmt.Println(string(jsonStreams[i]))
// Read Input
b := Book{}
err := json.Unmarshal(jsonStreams[i], &b)
if err == nil {
fmt.Printf("%+v\n", b)
} else {
fmt.Println(err)
fmt.Printf("%+v\n", b)
}
// Output as JSON
response := new(bytes.Buffer)
enc := json.NewEncoder(response)
enc.SetEscapeHTML(false)
enc.SetIndent("", " ")
err = enc.Encode(&b)
if err == nil {
fmt.Printf("%+v\n", response)
} else {
fmt.Println(err)
fmt.Printf("%+v\n", response)
}
}
}
Edit I have a solution which works for me. https://play.golang.org/p/Vr4eELsHs1
The keypoint was, that i have to take "fmt.Sprint(*isbn) to return the string in the marshaler. I created a new type, convert the input to int64 with the json.Number function and convert it with the json custom marshaler to string.
I have a solution which works for me. https://play.golang.org/p/Vr4eELsHs1
The keypoint was, that i have to take fmt.Sprint(*isbn)
to return the string in the marshaler. I created a new type, convert the input to int64 with the json.Number function and convert it with the json custom marshaler to string.
Thank you for your help!