# Specification of generating crdt.Object with literal
ref: https://pkg.go.dev/encoding/json#Marshal
kor : https://hackmd.io/hTqCSWCESqaWjRorXSTgUQ
# A. json.Array
#### 1. Use SetNewArray method
```go=
root.SetNewArray("k1")
```
#### 2. Initialize json.Array with specific type(including user defined struct) slice, array
> primitive, interface{ }, Counter, Text, Tree, []map[string]interface{ }, user defined struct
``` go=
// int
root.SetNewArray("k1", []int{0, 1, 2})
// void interface
root.SetNewArray("k2", []interface{}{0,1,2})
// Counter
cnt := json.NewCounter(0, crdt.LongCnt)
root.SetNewArray("counters", []json.Counter{cnt, cnt, cnt})
// User defined struct
type T1 struct {
msg string
Msg string
}
root.SetNewArray("structs", []T1{{"hello", "Hello"}, {"world", "World"}})
// typed slice in typed slice
arr := []int{1, 2, 3}
root.SetNewArray("arrays", []([]int){arr, arr})
// typed slice in typed array
arr := [3]int{1, 2, 3}
root.SetNewArray("arrays", []([3]int){arr})
```
# B. json.Object
#### 1. Use SetNewObject method
```go=
root.SetNewObject("obj")
```
#### 2. Initialize json.Object with Map[string]inteface{}
```go=
root.SetNewObject("obj", map[string]interface{}{ // 1: object
"str": "v", // 1: string
"arr": []interface{}{1, "str"}, // 3: array, 1, "str"
"obj": map[string]interface{}{"key3": 42.2}, // 2: object, 42.2
"cnt": json.NewCounter(0, crdt.LongCnt), // 1: counter
"txt": json.NewText(), // 1: text
"tree": json.NewTree(&json.TreeNode{ // 1: tree
Type: "doc",
Children: []json.TreeNode{{
Type: "p", Children: []json.TreeNode{{Type: "text", Value: "ab"}},
}},
}),
})
```
#### 3. Initialize json.Object with user defined struct
```go=
root.SetNewObject("obj", struct{ M string }{M: text})
```
- only exposed field in struct can be converted json.Object field.
> The struct and map forms can also receive addresses.
## B.1. Struct field tag
- You can use struct tags when you initializing json.Object, json.Array with user defined struct
- Tag follows the format below. Based on comma, the front is name and the back is option.
```format
`yorkie:(user defined name || - ),options`
```
> blank is allowed to name
options doesn't allow blank. (It will be trimed)
```go=
type Temp struct{
// user defined name, -
K1 string `yorkie:"-"` // case1
K2 string `yorkie:"k2"` // case2
// options
K3 string `yorkie:",omitEmpty"` // case3
}
```
### 1. - always omit
- `-` tag field omitted when generating crdt.Object
- In the case of 'yorkie:"-,omitEmpty"', the '-' will be treated user defined name.
```go=
struct {
M1 string `yorkie:"-"`
M2 string
}{M1: str, M2: str}
```
```shell=
{"obj":{"M2":"foo"}}
```
### 2. field name mapping
- You can define the field's key name without using the name of an existing field.
- `yorkie:"new_name,options"`
> unexposed field will not convert to json.elements
```go=
struct {
M1 string `yorkie:"m1"`
M2 string `yorkie:"m2"`
{M1: str, M2: str}
```
```shell=
{"obj":{"m1":"foo","m2":"foo"}}
```
### 3. omitEmpty
- The "omitEmpty" option specifies that the field should be omitted if the field has an empty value.
- The empty array is treated as empty.
```go=
// zero value
struct {
M1 string `yorkie:",omitEmpty"`
M2 string `yorkie:",omitEmpty"`
}{M1: str}
```
```shell=
{"obj":{"M1":"foo"}}
```
```go=
// empty array
struct {
M1 []int `yorkie:",omitEmpty"`
}{M1: []int{}}
```
```shell=
{"obj":{}}
```
## B.2. Nil, Zerovalue, Empty
---
```go
{"zeroValue int struct", struct{ M int }{}, `{"obj":{"M":0}}`},
{"zeroValue string struct", struct{ M string }{}, `{"obj":{"M":""}}`},
```
```go
{"zeroValue bytes struct", struct{ M []byte }{M: nil}, `{"obj":{"M":""}}`},
{"empty bytes struct", struct{ M []byte }{M: []byte{}}, `{"obj":{"M":""}}`},
{"zeroValue array struct", struct{ M []int }{M: nil}, `{"obj":{"M":[]}}`},
{"empty array struct", struct{ M []int }{M: []int{}}, `{"obj":{"M":[]}}`},
```
- handle empty array and nil in the same way
- The following table summarizes how the default values are handled when each field is declared in the structure
| Type | zero value(not initialized) | Empty value(initialized but empty) | Initialize method |
| --------------- | --------------- | --------------- | --------------- |
| int | 0 |
| String | "" | "" |""
| []byte | "" | "" | []byte
| json.Array | [ ] | [ ] | []int{}
| json.Counter | 0 | | NewCounter|
| json.Tree | {"type":"root","children":[]} | {"type":"root","children":[]} | NewTree
| json.Text | [ ] | [ ] | NewText
| json.Object | { } | |
| pointer | null | | nil
> Blank means there is no way
## B.3. Pointer
- The pointer in array, slice, struct interpreted *pointer(the value the pointer points to) when generating json.Object.
- but this conversion does not support for json.Text, Counter, Tree, Object. (& operater will not work for them)
```go=
// available
{"struct pointers", []*T1{&t1, &t1}, `[{"M":"a"},{"M":"a"}]`, 5},
{"array pointers", []*[3]int{&arr, &arr}, `[[1,2,3],[1,2,3]]`, 9},
// does not support
{"Counter Pointer", []*json.Counter{&json.NewCounter(1, crdt.LongCnt)}, `[1]`}
```
- If the pointer has null, it converted to null of json.primitive.
```go=
{"nested &struct with nil", struct{ M *T1 }{M: nil}, `{"obj":{"M":null}}`, 2},
```
- When generating json.Object, you can use pointer of map[string]interface{} or struct.
```go=
{"null &map", &map[string]interface{}{"M": nil}, `{"obj":{"M":null}}`, 2},
```
## B.4. Named type
- you can also use your named type.
```go=
type MyInt int
type S struct{ MyInt }
{"named type", struct{ M MyInt }{M: 5}, `{"obj":{"M":5}}`, 2},
{"named type", MyStruct{5}, `{"obj":{"M":5}}`, 2},
```
## B.5. Anonymous field
- If the anonymous field type starts with lowercase letters, it will be omitted.
```go=
type MyInt int
type S1 struct{ MyInt }
type S2 struct{ int }
{"anonymous field", S1{5}, `{"obj":{"MyInt":5}}`, 2}
{"lowercase", S2{5}, `{"obj":{}}`}
```
## B.6. Embedded struct
- It also support Embedded struct.
```go=
T4 struct {
T1
t1
M string
}
embedded := T4{
T1: T1{M: str},
t1: t1{M: str}, // It will be omitted
M: "foo",
}
{"embedded struct", embedded, `{"obj":{"M":"foo","T1":{"M":"foo"}}}`, 4},
{"&embedded struct", &embedded, `{"obj":{"M":"foo","T1":{"M":"foo"}}}`, 4},
```
## B.7. Unsupported Values
---
- If these values are included in the structure array, panic will occur.
```go=
pointerCycle,
pointerCycleIndirect,
mapCycle,
sliceCycle,
recursiveSliceCycle,
```