how to get data in interface{} while unmarshaling an XML in Golang? - go

I am trying to use interface{} to Marshal and UnMarshal my xml in golang. The reason is that as in calling a soap server my soap envelope, header are same but i want to pass the different soap function by passing different structs. I have made a sample code in playground(not related to soap). I am able to marshal the xml with interface{} but unable to unmarshal.
Here is link Play Ground
Please tell me what i am doing wrong ?

You can't unmarshal to an empty interface since the empty interface doesn't have any exported fields to map the xml keys/values to. If you want share your same code to "dynamically" handle the message differently, you should store it in a string or byte array (a byte array is recommended in this case). You then process the data based on your needs.
http://play.golang.org/p/sPq0ZfAcU7

Related

How to unmarshal protbuf data into custom struct in Golang

I have a proxy service that translate protobuf into another struct. I
can just write some manual code to do that, but that is inefficient and boilerplate. I can also transform the protobuf data to JSON, and deserlize the JSON data into the destination struct, but the speed is slow and it is CPU heavy.
The Unmarshaler interface is now deprecated, and Message interface have internal types which I cannot implement in my project.
Is there a way I can do this now?
Psuedo code: basically, if Go's reflection supports setting and getting of struct / class fields by some sort of field identifier, then you can do this. Something like this in C# works, so long as the field types in the two classes are the same (because in C#, I'm doing object = object, which ends up being OK if they're the same actual type).
SourceStructType sourceStruct;
DestStructType destStruct;
foreach (Field sourceField in sourceStruct.GetType().GetFields())
{
Field destField = destStruct.GetType().FindFieldByName(sourceField.name);
destStruct.SetFieldValue(destField) = sourceStruct.GetFieldValue(sourceField);
}
If the structs are more complex - i.e. they have structs within them, then you'll have to recurse down into them. It can get fiddly, but once written you'll never have to write it ever again!

inconsistent behavior of json.Unmarshal into a map with custom types vs into a struct or slice

I have a custom type, which is supposed to be an enumerator, and it implements json.Unmarshaler.
When I unmarshal into a slice, or a struct of this type, it works, like https://go.dev/play/p/DGg3nzo_VwN
When I unmarshal into a map containing this type, it breaks, like https://go.dev/play/p/YGgnRvr0agz
Crawling through the source code (go 1.18), I know how to make it work, just implement encoding.TextUnmarshaler, like https://go.dev/play/p/vY4E4snAY52 and I also have learned how the code works for maps: it checks if encoding.TextUnmarshaler is implemented, if yes, call its UnmarshalJSON before trying UnmarshalText. In other words, UnmarshalText must be present, however it will be ignored if UnmarshalJSON is also present.
Why is this precedence? Why only maps are treated this way?
From Go's decoder:
// Map key must either have string kind, have an integer kind,
// or be an encoding.TextUnmarshaler.
So you must implement TextUnmarshaller.

Why are unexported struct fields purposely not marshalled in the json package

In the json package if you want to utilize tags to marshall and unmarshall structs the field must be exported. I always thought this was a limitation on the reflect package but it seems to be explicitly rejected here.
I would like to know what I am missing or the design choices behind this as it creates one of the following issues normally.
Exporting more fields than I want allowing users to change values without using potential getters and setters.
A lot of extra code if you chose to solve the above problem by making a second identical struct just for tag usage and make it unexported.
Here is a playground of code being able to read unexported tags.
Edit: Better playground thanks to #mkopriva

Golang gRPC database serialization key format defined on struct

I want to use the go structs that are generated by the gRPC compiler directly for database transactions but the problem is that only the json serialization field is set by gRPC.
Is there a way to either set additional serialization keys (like shown below) or is there another golang specific way to tell the database driver (sqlx on top of database/sql) that the json key format should be used?
Some example - The gRPC compiler creates the following struct:
type HelloWorld struct {
TraceId string `protobuf:"bytes,1,opt,name=trace_id,json=traceId,proto3" json:"trace_id,omitempty"`
...
What I would like to have:
type HelloWorld struct {
TraceId string `db:"trace_id" protobuf:"bytes,1,opt,name=trace_id,json=traceId,proto3" json:"trace_id,omitempty"`
...
A temporary workaround would be to write sql queries that use aliases (traceid instead of trace_id in this example) but it doesn't feel consistent and adds a lot of complexity.
I think that currently there is no built-in way of doing this. However, you might be interested in following this thread: https://github.com/golang/protobuf/issues/52
Other than that I think you can just create yet another struct for database access and make the mapping explicit which might be more readable.

When using gob to serialiaze structs over the wire, why do we need to Register() any fields that are interfaces inside the transmitted struct?

If we were to send
type ABC struct{
i interface{}
}
gob requires us to register the concrete type hidden behind our interface{}.
Why can't gob use reflection to identify the underlying concrete class in the field by itself.
That is, we need to use the Register method to tell gob what the concrete type is.
Given the method signature looks like this Register(value interface{}), gob already uses reflection to fully identify the type passed to the method.
Why doesn't gob iterate through the instantiated ABC struct at runtime and perform Register automatically?

Resources