Json marshal map of structs results in empty object - go

I have a simple object defined:
type Link struct {
Href string `json:"href"`
Title string `json:"href,omitempty"`
}
type Foo struct {
Links map[string]Link `json:"_links"`
}
foo := new(Foo)
foo.Links = make(map[string]Link, 0)
foo.Links["self"] = Link{Href: "/href"}
After marshalling it to JSON, I'd expect:
{
"_links": {
"self": {
"href": "/href"
}
}
}
But instead I get:
{
"_links": {
"self": {}
}
}
Any idea why? Here's a full example:
https://play.golang.org/p/3RA3Mrx3pt

You've defined json:"href" twice:
type Link struct {
Href string `json:"href"`
Title string `json:"href,omitempty"`
}
After changing the second to json:"title" it works: https://play.golang.org/p/uEbyqtHYF8.

Related

How to request the schema from a GraphQL service using curl?

I have a curl script (as a standin for real code) that can POST to my company's GraphQL endoint and get data. It's working fine.
It appears that it should also be possible to get the "schema" by crafting the appropriate request, but I have not found any way to do that at a HTTP level.
If it is possible, what would the curl look like (the data)?
Are there other requests other than "query" that I can use to gleen other information?
The body you need is pretty involved for an introspection query, but I think you're looking for something like this
introspection_query.json:
{
"query": "query IntrospectionQuery {
__schema {
queryType { name }
mutationType { name }
subscriptionType { name }
types {
...FullType
}
directives {
name
description
locations
args {
...InputValue
}
}
}
}
fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}
fragment InputValue on __InputValue {
name
description
type { ...TypeRef }
defaultValue
}
fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
}
}
}
}"
}
and then you can do
curl -i -X POST http://localhost:8080/graphql -H "Content-Type: application/json" -d #introspection_query.json
Shamefully stolen from
https://gist.github.com/martinheld/9fe32b7e2c8fd932599d36e921a2a825

What does { .. } mean in a pattern?

I found the following piece of code in the doc about actix:
#[macro_use]
extern crate failure;
use actix_web::{error, http, HttpResponse};
#[derive(Fail, Debug)]
enum UserError {
#[fail(display = "Validation error on field: {}", field)]
ValidationError { field: String },
}
impl error::ResponseError for UserError {
fn error_response(&self) -> HttpResponse {
match *self {
UserError::ValidationError { .. } =>
HttpResponse::new(http::StatusCode::BAD_REQUEST),
}
}
}
What does { .. } mean here?
It's a pattern-matching destructuring wildcard that allows one to not need to specify all the members of an object. In this case:
UserError::ValidationError { .. }
It is enough for that match branch that the enum variant is ValidationError, regardless of its contents (in this case field):
enum UserError {
#[fail(display = "Validation error on field: {}", field)]
ValidationError { field: String },
}
It is also useful when one is concerned only with some members of an object; consider a Foo struct containing baz and bar fields:
struct Foo {
bar: usize,
baz: usize,
}
If you were only interested in baz, you could write:
fn main() {
let x = Foo { bar: 0, baz: 1 };
match x {
Foo { baz, .. } => println!("{}", baz), // prints 1
_ => (),
}
}

Remove Element From Struct But Only For This One Function

So I have an Struct that holds data that has a AddedByUser which links to my User Struct.
What I want to be able to do it remove the UserLevel from the AddedByUser
Now I want to be able to do it from this function only, so using the json:"-" is not an option. That would remove it from all json output. I only want to remove it form this one function.
I should also say that these are Gorm models and when I have been trying to remove the 10 option (UserLevels) it only removes the outer data set not the UserLevel from all of the data.
{
"ID": 1,
"CreatedAt": "2019-01-08T16:33:09.514711Z",
"UpdatedAt": "2019-01-08T16:33:09.514711Z",
"DeletedAt": null,
"UUID": "00000000-0000-0000-0000-000000000000",
"Title": "title000",
"Information": "info999",
"EventDate": "2006-01-02T15:04:05Z",
"AddedByUser": {
"ID": 2,
"CreatedAt": "2019-01-08T15:27:52.435397Z",
"UpdatedAt": "2019-01-08T15:27:52.435397Z",
"DeletedAt": null,
"UUID": "b019df80-a7e4-4397-814a-795e7e84b4ca",
"Firstname": "Me",
"Surname": "admin",
"Password": "....",
"Email": "admin#email.co.uk",
"UserLevel": {
"ID": 0,
"CreatedAt": "0001-01-01T00:00:00Z",
"UpdatedAt": "0001-01-01T00:00:00Z",
"DeletedAt": null,
"LevelTitle": "",
"UserLevel": null
},
So this is what I have tried,
data := []models.MyData{}
data = append(data[0:2])
I have about 14 results, with out the append it loads all the results but with this is only loads two results. The idea was to remove either UpdateAt or Title. As I am not sure if the gorm model information is all 0 or if the slice sees them as 0,1,2,3,4 etc.
I have also tried to range over the slice of models, while I can access each of the sections, I can not seem to find a simple method to remove data by name from a struct? Maps seem to have that but not structs which I am not sure why?
Thanks.
UPDATE
This is the model I am using:
//Model
type MyData struct {
gorm.Model
UUID uuid.UUID
Title string
Information string
EventDate time.Time
AddedByUser Users `gorm:"ForeignKey:added_by_user_fk"`
AddedByUserFK uint
}
//Users Model
type Users struct {
gorm.Model
UUID uuid.UUID
Firstname string
Surname string
Password string
Email string
UserLevel UserLevels `gorm:"ForeignKey:user_level_fk" json:",omitempty"`
UserLevelFK uint
}
As mentioned in the comments, you cannot remove fields from a struct value, because that would yield a value of a different type.
However, you can set fields to their zero value. Combined with the omitempty JSON tag, you can exclude fields from the JSON encoding. To make this work properly, you have to change the UserLevel field to a pointer type (otherwise you end up with empty objects in the JSON document).
Types shortened for brevity:
package main
import (
"encoding/json"
"fmt"
)
type MyData struct {
Title string
AddedByUser Users
}
type Users struct {
ID int
UserLevel *UserLevels `json:",omitempty"` // pointer type with omitempty
}
type UserLevels struct {
LevelTitle string
}
func main() {
var x MyData
x.Title = "foo"
x.AddedByUser.ID = 2
x.AddedByUser.UserLevel = &UserLevels{}
f(x)
b, _ := json.MarshalIndent(x, "", " ")
fmt.Println("main:\n" + string(b))
}
func f(x MyData) {
// "unset" UserLevel. Since we are receiving a copy of MyData, this is
// invisible to the caller.
x.AddedByUser.UserLevel = nil
b, _ := json.MarshalIndent(x, "", " ")
fmt.Println("f:\n" + string(b))
}
// Output:
// f:
// {
// "Title": "foo",
// "AddedByUser": {
// "ID": 2
// }
// }
// main:
// {
// "Title": "foo",
// "AddedByUser": {
// "ID": 2,
// "UserLevel": {
// "LevelTitle": ""
// }
// }
// }
Try it on the playground: https://play.golang.org/p/trUgnYamVOA
Alternatively, you can define new types that exclude the AddedByUser field. However, since this field isn't at the top level, this is a lot of work, and it's easy to forget to update those types when new fields are added to the original types.
If the field were at the top level, the compiler would do most of the work for you, because types that only differ in their field tags can be directly converted to one another:
type MyData struct {
ID int
Title string
}
func main() {
var x MyData
x.ID = 1
x.Title = "foo"
f(x)
}
func f(x MyData) {
type data struct { // same as MyData, except the field tags
ID int
Title string `json:"-"`
}
b, _ := json.MarshalIndent(data(x), "", " ")
fmt.Println("main:\n" + string(b))
}

how to query prismic slices and returning data from each slice

I'm trying to use Gatsby's /___graphq debugger and the README file for gatsby-source-prismic says you can return slices. So below I'm returning the slice with a name PrismicProductBodySteps.
{
allPrismicHomePage {
edges {
node {
data {
seo_title
body {
__typename
... on PrismicProductBodySteps {
}
}
}
}
}
}
}
}
Can someone explain to me what ... on PrismicProductBodySteps means ?
In a gatsby component I've seen this as an example.
body {
... on PrismicProductsBodySteps {
...ProductStepsFragment
}
Can anyone explain to me what the ...ProductStepsFragment means ?
PrismicProductBodySteps would be a custom node type name representing a dynamic series of content blocks. That custom node type name is coming from a Prismic data model; yours will likely be different.
According to the gatsby-source-prismic documentation, using custom node type names requires you to figure out what they are first:
The easiest way to get the type of nodes is to use the /___graphql
debugger and run the below query (adjust the document type and field
name).
{
allPrismicPage {
edges {
node {
id
data {
body {
__typename
}
}
}
}
}
}
Once you have your custom node type name, you can use a GraphQL fragment to pull data specific to each fragment. Again, this would depend on how you have the fragments defined in your data model, but it would look something like this:
{
allPrismicHomePage {
edges {
node {
data {
seo_title
body {
__typename
... on PrismicYourContentBlockOne {
text {
html
}
}
... on PrismicYourContentBlockTwo {
text {
html
}
}
... on PrismicYourContentBlockThree {
text {
html
}
}
}
}
}
}
}
}

Unmarshal custom types with jsonpb

What's the best way to convert this json object to protobuf?
JSON:
{
"name": "test",
"_list": {
"some1": { "value": 1 },
"some2": [
{ "value": 2 },
{ "value": 3 },
]
}
}
Proto:
message Something {
string name = 1;
message ListType {
repeated string = 1;
}
map<string, ListType> _list = 2;
}
Without having the _list in the message I would use jsonpb.Unmarsal, but I can't think of a way to define the Unmarshaler interface on a type that is generated in a diff package.
I also thought of having _list as a Any (json.RawMessage) and handle it after the Unmarshal (but can't make this to work; err message: Any JSON doesn't have '#type')
With _list being inconsistent (not just a list of strings/map of values/etc) and you mentioning you looked into using Any you could consider making your message:
message Something {
string name = 1;
google.protobuf.Struct _list = 2;
}
https://github.com/golang/protobuf/blob/master/ptypes/struct/struct.proto
With that you can marshal/unmarshal json to/from proto messages using github.com/golang/protobuf/jsonpb which is actually designed for use with the grpc gateway but you can use it too

Resources