I've got two models, Dictionary and DictionaryRecord with a foreign key on Dictionary.
type DictionaryRecord struct {
Id string `gorm:"primaryKey"`
Name string
DictionaryId string
}
type Dictionary struct {
Id string `gorm:"primaryKey"`
Name string
Records []DictionaryRecord
}
I'd like to make sure that when creating a dictionary with a nested record changed, to have the change reflected during the upsert.
package main
import (
// Sqlite driver based on GGO
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
func main() {
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})
if err != nil {
panic(err)
}
db.AutoMigrate(
&DictionaryRecord{},
&Dictionary{},
)
db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
DoUpdates: clause.AssignmentColumns([]string{"name"}),
}).Create(&Dictionary{
Name: "AAAAA",
Id: "e831ab86-db60-4a71-ba63-f20a181cd69b",
Records: []DictionaryRecord{
{
Id: "66f73e9b-61b8-4bc9-941d-80d7fd80f8f4",
Name: "will be updated",
},
},
})
}
How do you specify that the column name in the DictionaryRecord must be updated?
can you try use pointer
type DictionaryRecord struct {
Id string `gorm:"primaryKey"`
Name string
DictionaryId string
}
type Dictionary struct {
Id string `gorm:"primaryKey"`
Name string
Records []*DictionaryRecord //on this records
}
Related
I want to print out the first "row" of my JSON that is within a struct in Go. The JSON looks like
[
{
"id":"7",
"username":"user",
"subject":"subject",
"message":"message"
},
{
"id":"6",
"username":"user2",
"subject":"subject2",
"message":"message2"
},
{
"id":"5",
"username":"user3",
"subject":"subject3",
"message":"message3"
},
{
"id":"4",
"username":"user4",
"subject":"subject4",
"message":"message4"
},
{
"id":"3",
"username":"user5",
"subject":"subject5",
"message":"message5"
},
{
"id":"2",
"username":"user6",
"subject":"subject6",
"message":"message6"
},
{
"id":"1",
"username":"user7",
"subject":"subject7",
"message":"message7"
}
]
I have put it in a Struct like this
type Info struct {
Id string
Username string
Subject string
Message string
}
infoJson := html;
var information []Info;
err2 := json.Unmarshal([]byte(infoJson), &information);
if err2 != nil {
fmt.Println(err2);
}
And then I can print all of them out using
for _, info := range information {
fmt.Println(info.Id + " " + info.Username);
fmt.Println(info.Subject);
fmt.Println(info.Message);
}
I would like to just be able to print out the JSON that is aligned with a specific id. For example, I wish to be able to specify 7 and then all the things that are in the id:7 JSON row will be printed out in the above format. So it should print out:
7 user
subject
message
How can I do this?
If you want to print the "first" item. Then you can certainly use the index of the item to do that.
fmt.Println(information[0])
If you want to print a specific item, then you would have to iterate using range and check if the item matches the condition.
It may be more helpful to build a map of the items, in this case using ID as the key.
// Print the first item.
fmt.Println(information[0])
// Create a map to index items by ID.
dictionary := make(map[string]Info)
for _, info := range information {
dictionary[info.Id] = info
}
element, ok := dictionary["7"]
if !ok {
fmt.Println("Not found.")
return
}
fmt.Println(element)
You can also add a method on Info to contain the formatting logic.
func (i *Info) Print() string {
return fmt.Sprintf("%s %s\n%s\n%s\n", i.Id, i.Username, i.Subject, i.Message)
}
And then simply call that:
// Print the first item.
fmt.Println(information[0].Print())
I have this data schema:
"person": {
"name": "John",
"pets": [
{
"name": "Birdie"
}
]
}
This is the struct to insert the Person document to MongoDB:
type Person struct {
Id primitive.ObjectID `bson:"_id,omitempty" json:"id"`
Name string `json:"name"`
Pets []struct {
Name string `json:"name"`
} `json:"pets"
}
When JSON is sent to the POST Person API without the pets field, the MongoDB document recorded has pets field set as null. I think this is because slices in go has zero value of nil instead of empty array?
personPostRequest := ds.Person{}
if err := c.ShouldBindJSON(&personPostRequest); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
Having pets initialized as null is troublesome because I can't use addToSet when adding pets to the document:
// Will render the error Cannot apply $addToSet to non-array field.
// Field named 'pets' has non-array type null
err = collection.FindOneAndUpdate(
ctx,
bson.M{"_id": personId},
bson.M{
"$addToSet": bson.M{
"pets": bson.M{"$each": pets},
},
},
&opt,
)
I can solve this problem by adding the struct tag bson:,omitempty to pets but I like to explore the solution where I can initialized pets to empty array in MongoDB.
How do I do this in Go? I'm using Go gin framework. Thanks
I have a function that filters an array of objects and reduces to one String. The array has this format:
[Person(destination: “city”, surname: [“sur”, “name”]]
This is the function that filters the persons to find the surname by a certain name.
And I have three states of name: "john", "paul", "james". I want to verify if each name exists and to do something with his surname. How can I do this without using if...else. I don't like how it looks with all this if's.
enum Destination: String, RawRepresentable {
case city
case rural
case both
}
func findPerson(person: persons, type: Destination) -> String? {
let surname = persons.filter{ $0.destination == type.rawValue}.reduce("") { id, element in
return element.details.joined(separator: " ")
}
return surname
}
func findPersons(person: persons) {
// Also I want to verify if is not null the string that i receive
if let city = self.findPerson(person: person, type: .city) {
self.handleCity(type: city)
}
if let rural = self.findPerson(person: person, type: .rural) {
self.handleRural(type: rural)
}
if let both = self.findPerson(person: person, type: .both) {
self.handleBoth(type: both)
}
}
enum Destination: String, RawRepresentable {
case city
case rural
case both
static let all : [Destination] = [
.city,
.rural,
.both
]
func findPersons(person: persons) {
// Also I want to verify if is not null the string that i receive
for destination in Destination.all{
if let findPerson(person, type: destination){
self.handleCity(type: destination.rawValue)
}
}
}
How to unmarshal the json and fill into structures. Like i'm having salesorder and salesorderdetails structures. In json i will have 1 record for salesorder and multiple items for salesorderdetails structure.
Here is the go code i have tried with single item and for multiple items, but working only for single record for salesorderdetails structure.
Gocode:
package main
import (
"encoding/json"
"fmt"
)
type Order struct {
SalesId string `json:"sales_id"`
Customer string `json:"customer_name"`
TotalPrice string `json:"totalprice"`
}
type OrderDetails struct {
DetailId string `json:"detail_id"`
SalesId string `json:"sales_id"`
ItemName string `json:"item_name"`
Qty string `json:"qty"`
Price string `json:"price"`
}
type Temp struct {
Salesorder Order `json:"Salesorder"`
Salesorderdetails OrderDetails `json:"OrderDetails"`
}
func main() {
jsonByteArray := []byte(`[{"Salesorder":{"sales_id":"SOO1","customer_name":"CUST1","totalprice":"200"}, "OrderDetails":{"detailid":"1","sales_id":"SOO1","item_name":"ITEM1","qty":"2","price":"100"}}]`)
//if i use above json it is working and if i use below json its not working
//jsonByteArray := []byte(`[{"Salesorder":{"sales_id":"SOO1","customer_name":"CUST1","totalprice":"200"}, "OrderDetails":{"detailid":"1","sales_id":"SOO1","item_name":"ITEM1","qty":"2","price":"100"},{"detailid":"2","sales_id":"SOO2","item_name":"ITEM2","qty":"3","price":"200"}}]`)
var temp []Temp
err := json.Unmarshal(jsonByteArray, &temp)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", temp)
fmt.Printf("%+v\n ", temp[0].Salesorder.SalesId)
}
Error while using multiple items:
panic: invalid character '{' looking for beginning of object key string
Output while using single item with success:
[{Salesorder:{SalesId:SOO1 Customer:CUST1 TotalPrice:200} Salesorderdetails:{SalesId:SOO1 ItemName:ITEM1 Qty:2 Price:100}}]
SOO1
Fiddle: updated with key in salesorderdetails
https://play.golang.org/p/klIAoNi18r
What you are tying to decode is not valid JSON. This would be valid:
{
"Salesorder": {
"sales_id": "SOO1",
"customer_name": "CUST1",
"totalprice": "200"
},
"OrderDetails": {
"sales_id": "SOO1",
"item_name": "ITEM1",
"qty": "2",
"price": "100"
}
}
But what you are giving is this:
{
"Salesorder": {
"sales_id": "SOO1",
"customer_name": "CUST1",
"totalprice": "200"
},
"OrderDetails": {
"sales_id": "SOO1",
"item_name": "ITEM1",
"qty": "2",
"price": "100"
},
{ // Things become invalid here
"sales_id": "SOO2",
"item_name": "ITEM2",
"qty": "3",
"price": "200"
}
}
It looks like you are trying to give a list of objects, in which case you need to wrap those objects in square brackets [] or you will have to give the second OrderDetails object its own key.
Try this:
package main
import (
"encoding/json"
"fmt"
)
type Order struct {
SalesId string `json:"sales_id"`
Customer string `json:"customer_name"`
TotalPrice string `json:"totalprice"`
}
type OrderDetails struct {
SalesId string `json:"sales_id"`
ItemName string `json:"item_name"`
Qty string `json:"qty"`
Price string `json:"price"`
}
type Temp struct {
Salesorder Order `json:"Salesorder"`
Salesorderdetails []OrderDetails `json:"OrderDetails"`
}
func main() {
jsonByteArray := []byte(`[{"Salesorder":{"sales_id":"SOO1","customer_name":"CUST1","totalprice":"200"}, "OrderDetails":[{"sales_id":"SOO1","item_name":"ITEM1","qty":"2","price":"100"},{"sales_id":"SOO2","item_name":"ITEM2","qty":"3","price":"200"}]}]`)
var temp []Temp
err := json.Unmarshal(jsonByteArray, &temp)
if err != nil {
panic(err)
}
//fmt.Printf("%+v\n", temp)
// Printing all Orders with some details
for _, order := range temp {
fmt.Println("Customer:", order.Salesorder.Customer)
for _, details := range order.Salesorderdetails {
fmt.Printf(" ItemName: %s, Price: %s\n", details.ItemName, details.Price)
}
}
}
.. OrderDetails is an array now
I am trying to get each JSON object out of a JSON array. I get this data via a HTTP post.
I know what my data will look like:
{
"array":[
{
"entity_title":"University of Phoenix",
"entity_org_name":"CS Club",
"possible_user_name":"Johnny Ive",
"posibble_user_email":"Johhny.Ive#uop.edu",
"user_position_title":"President",
"msg_body_id":4
},
{
"entity_title":"University of San Francisco",
"entity_org_name":"Marketing club",
"possible_user_name":"steve jobs",
"posibble_user_email":"steven.job#uop.edu",
"user_position_title":"Student",
"msg_body_id":5
}
]
}
My example code and my structs look like this:
type MsgCreateUserArray struct {
CreateUser []MsgCreateUserJson `json:"createUserArray"`
}
type MsgCreateUserJson struct {
EntityTitleName string `json:"entity_title_name"`
EntityOrgName string `json:"entity_org_name"`
PossibleUserName string `json:"possible_user_name"`
PossibleUserEmail string `json:"possible_user_email"`
UserPositionTitle string `json:"user_position_title"`
MsgBodyId string `json:"msg_body_id, omitempty"`
}
func parseJson(rw http.ResponseWriter, request *http.Request) {
decodeJson := json.NewDecoder(request.Body)
var msg MsgCreateUserArray
err := decodeJson.Decode(&msg)
if err != nil {
panic(err)
}
log.Println(msg.CreateUser)
}
func main() {
http.HandleFunc("/", parseJson)
http.ListenAndServe(":1337", nil)
}
I am not sure where how to iterate over the JSON array and get the JSON objects and then just work with the JSON objects.
Try this as your structs,
type MsgCreateUserArray struct {
CreateUser []MsgCreateUserJson `json:"array"`
}
type MsgCreateUserJson struct {
EntityOrgName string `json:"entity_org_name"`
EntityTitle string `json:"entity_title"`
MsgBodyID int64 `json:"msg_body_id,omitempty"`
PosibbleUserEmail string `json:"posibble_user_email"`
PossibleUserName string `json:"possible_user_name"`
UserPositionTitle string `json:"user_position_title"`
}
Your entity_title_name is not named correctly, nor is the top level array. After you decode into a MsgCreateUserArray you can iterate over the CreateUser slice to get each MsgCreateUserJson