How to apply my UnmarshalJSON method to an inline structure?

So, I have a structure P. I need to unmount some json data in P, but sometimes it comes with built-in struct, Embedded. In any case, I canceled json from the API and you need to format the "Formatted" field. It seems that in the Embedded case, my unmarshaller is not called.

I have the following code :

package main

import (
    "encoding/json"
    "fmt"
)

type P struct {
    Name      string `json:"name"`
    Formatted string `json:"formatted"`
}

type Embedded struct {
    A struct {
        B struct {
            *P
        } `json:"b"`
    } `json:"a"`
}

func (p *P) UnmarshalJSON(b []byte) error {
    type Alias P

    a := &struct {
        *Alias
    }{
        Alias: (*Alias)(p),
    }

    if err := json.Unmarshal(b, &a); err != nil {
        return err
    }

    a.Formatted = fmt.Sprintf("Hi, my name is %v", a.Name)

    return nil
}

func simple() {
    b := []byte(`{"name":"bob"}`)

    p := &P{}
    if err := json.Unmarshal(b, &p); err != nil {
        panic(err)
    }

    fmt.Printf("normal: %+v\n", p)
}

func embedded() {
    b := []byte(`{"a":{"b":{"name":"bob"}}}`)

    e := &Embedded{}
    if err := json.Unmarshal(b, &e); err != nil {
        panic(err)
    }

    fmt.Printf("embedded: %+v\n", e.A.B.P)
}

func main() {
    simple()

    embedded()

}

(I understand that I can get rid of the custom unmarshaller and create a name formatting method, but would like to see if this is possible.)

+4
source share
2 answers

I don’t know enough to explain all the reasons, I’ll just list what works and what doesn’t. Someone more knowledgeable may fill you with the reasons for this.

, B *struct, , .

type Embedded struct {
    A struct {
        B *struct {
            P
        } `json:"b"`
    } `json:"a"`
}

. , , *struct .

type embedP struct {
            P
}

type Embedded struct {
    A struct {
        B embedP `json:"b"`
    } `json:"a"`
}

, *P .

type embedP struct {
            *P
}

type intermediate struct {
        B embedP `json:"b"`
}

type Embedded struct {
    A  intermediate `json:"a"`
}

e := &Embedded{A:intermediate{embedP{P:&P{}}}}

.

type Embedded struct {
    A struct {
        B struct {
            *P
        } `json:"b"`
    } `json:"a"`
}

e := &Embedded{A : struct{B struct{*P}`json:"b"`}{B: struct{*P}{&P{}}}}

p := &P{} , & p json.Unmarshal. json.Unmarshal(b, p) . e := &Embedded{}.

+2

@John , json-, indirect(v reflect.Value, decodingNull bool) line 442-483.

// v ,
// , .
// Unmarshaler, .
// decodingNull , , nil.

json.Unmarshaler, encoding.TextUnmarshaler v.

  • v , , , v json.Unmarshaler/encoding.TextUnmarshaler . nil unmarshaller, , B unmarshaller .
  • v , , v json.Unmarshaler/encoding.TextUnmarshaler . , v nil, v.

Embedded

type Embedded struct {
    A struct {
        B struct {
            *P
        } `json:"b"`
    } `json:"a"`
}

, "b":{"name":"bob"} B, B , (1) . unmarshaller nil, . - json B.

Embedded

type Embedded struct {
    A struct {
        *B struct {
            P
        } `json:"b"`
    } `json:"a"`
}

B , (2) . struct{*P} B, , B unmarshaller, .

type Embedded struct {
    A struct {
        *B struct {
            *P
        } `json:"b"`
    } `json:"a"`
}

, P ,

//...
e := Embedded{}
e.A.B = &struct{ *P }{P: &P{}}
//...

, (2) &struct{*P}{} B, unmarshaller B.P == nil. json B.P unmarshall.

:
, , , .

+2

Source: https://habr.com/ru/post/1687182/


All Articles