Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Go-JSON #14914

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ For imports you should use the following format (_without_ the comments)
```go
import (
// stdlib
"encoding/json"
"fmt"

// local packages
Expand Down
2 changes: 2 additions & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ RUN_USER = ; git
;;
;; Application run mode, affects performance and debugging. Either "dev", "prod" or "test", default is "prod"
RUN_MODE = ; prod
;; JSON library to use. Either "std", "goccy", or "jsoniter". Will default to "jsoniter"
; JSON_LIBRARY = jsoniter

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Expand Down
2 changes: 2 additions & 0 deletions docs/content/doc/advanced/config-cheat-sheet.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
- `RUN_USER`: **git**: The user Gitea will run as. This should be a dedicated system
(non-user) account. Setting this incorrectly will cause Gitea to not start.
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging. Either "dev", "prod" or "test".
- `JSON_LIBRARY`: **jsoniter**: JSON library to use. Either "std", "goccy", or "jsoniter". Will default to "jsoniter"


## Repository (`repository`)

Expand Down
1 change: 1 addition & 0 deletions docs/content/doc/installation/from-source.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ using the `LDFLAGS` environment variable for `make`. The appropriate settings ar
- For `AppWorkPath` you should use `-X \"code.gitea.io/gitea/modules/setting.AppWorkPath=working-path\"`
- For `StaticRootPath` you should use `-X \"code.gitea.io/gitea/modules/setting.StaticRootPath=static-root-path\"`
- To change the default PID file location use `-X \"code.gitea.io/gitea/modules/setting.PIDFile=/run/gitea.pid\"`
- To change the default JSON library use `-X \"code.gitea.io/gitea/modules/json.DefaultJSONHandlerType=<library-type std, goccy or jsoniter>\"`

Add as many of the strings with their preceding `-X` to the `LDFLAGS` variable and run `make build`
with the appropriate `TAGS` as above.
Expand Down
1 change: 1 addition & 0 deletions docs/content/doc/usage/command-line.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ All global options can be placed at the command level.
- `--custom-path path`, `-C path`: Location of the Gitea custom folder. Optional. (default: `AppWorkPath`/custom or `$GITEA_CUSTOM`).
- `--config path`, `-c path`: Gitea configuration file path. Optional. (default: `custom`/conf/app.ini).
- `--work-path path`, `-w path`: Gitea `AppWorkPath`. Optional. (default: LOCATION_OF_GITEA_BINARY or `$GITEA_WORK_DIR`)
- `--json-library`: JSON library to use. Optional. (default: `jsoniter`, but may be: `std`, `goccy` or `jsoniter`)

NB: The defaults custom-path, config and work-path can also be
changed at build time (if preferred).
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ require (
github.com/go-swagger/go-swagger v0.27.0
github.com/go-testfixtures/testfixtures/v3 v3.6.1
github.com/gobwas/glob v0.2.3
github.com/goccy/go-json v0.7.9
github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,9 @@ github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/V
github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/goccy/go-json v0.7.4 h1:B44qRUFwz/vxPKPISQ1KhvzRi9kZ28RAf6YtjriBZ5k=
github.com/goccy/go-json v0.7.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.7.9 h1:mSp3uo1tr6MXQTYopSNhHTUnJhd2zQ4Yk+HdJZP+ZRY=
github.com/goccy/go-json v0.7.9/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0=
github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
Expand Down
16 changes: 15 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"code.gitea.io/gitea/cmd"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"

Expand Down Expand Up @@ -99,6 +100,11 @@ arguments - which can alternatively be run by running the subcommand web.`
Value: setting.AppWorkPath,
Usage: "Set the gitea working path",
},
cli.StringFlag{
Name: "json-library",
Value: json.DefaultJSONHandlerType,
Usage: "Set the default json library type",
},
}

// Set the default to be equivalent to cmdWeb and add the default flags
Expand Down Expand Up @@ -130,10 +136,14 @@ func establishCustomPath(ctx *cli.Context) error {
var providedCustom string
var providedConf string
var providedWorkPath string
var defaultJSONHandler string

currentCtx := ctx
for {
if len(providedCustom) != 0 && len(providedConf) != 0 && len(providedWorkPath) != 0 {
if len(providedCustom) != 0 &&
len(providedConf) != 0 &&
len(providedWorkPath) != 0 &&
len(defaultJSONHandler) != 0 {
break
}
if currentCtx == nil {
Expand All @@ -148,9 +158,13 @@ func establishCustomPath(ctx *cli.Context) error {
if currentCtx.IsSet("work-path") && len(providedWorkPath) == 0 {
providedWorkPath = currentCtx.String("work-path")
}
if currentCtx.IsSet("json-library") && len(defaultJSONHandler) == 0 {
defaultJSONHandler = currentCtx.String("json-library")
}
currentCtx = currentCtx.Parent()

}
json.SelectDefaultJSONHandler(defaultJSONHandler)
setting.SetCustomPathAndConf(providedCustom, providedConf, providedWorkPath)

setAppHelpTemplates()
Expand Down
59 changes: 59 additions & 0 deletions modules/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
"encoding/binary"
"encoding/json"
"io"
"strings"

goccy_json "github.com/goccy/go-json"
jsoniter "github.com/json-iterator/go"
)

Expand All @@ -32,14 +34,43 @@ type Interface interface {
Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error
}

// DefaultJSONHandlerType is the type of library used as the backend for the JSON library
var DefaultJSONHandlerType = "jsoniter"

var (
// DefaultJSONHandler default json handler
DefaultJSONHandler Interface = JSONiter{jsoniter.ConfigCompatibleWithStandardLibrary}

_ Interface = StdJSON{}
_ Interface = JSONiter{}
_ Interface = GoCcyJSON{}
)

func init() {
SelectDefaultJSONHandler(DefaultJSONHandlerType)
}

// SelectDefaultJSONHandler selects the default JSON handler
// Note: this function is not race safe and would need to be run before other uses
func SelectDefaultJSONHandler(typ string) {
if typ == DefaultJSONHandlerType {
return
}
switch strings.ToLower(typ) {
case "std":
DefaultJSONHandler = StdJSON{}
DefaultJSONHandlerType = "std"
case "goccy":
DefaultJSONHandler = GoCcyJSON{}
DefaultJSONHandlerType = "goccy"
case "jsoniter":
fallthrough
default:
DefaultJSONHandler = JSONiter{jsoniter.ConfigCompatibleWithStandardLibrary}
DefaultJSONHandlerType = "jsoniter"
}
}

// StdJSON implements Interface via encoding/json
type StdJSON struct{}

Expand Down Expand Up @@ -98,6 +129,34 @@ func (j JSONiter) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) e
return json.Indent(dst, src, prefix, indent)
}

// GoCcyJSON implements Interface
type GoCcyJSON struct{}

// Marshal implements Interface
func (j GoCcyJSON) Marshal(v interface{}) ([]byte, error) {
return goccy_json.Marshal(v)
}

// Unmarshal implements Interface
func (j GoCcyJSON) Unmarshal(data []byte, v interface{}) error {
return goccy_json.Unmarshal(data, v)
}

// NewEncoder implements Interface
func (j GoCcyJSON) NewEncoder(writer io.Writer) Encoder {
return goccy_json.NewEncoder(writer)
}

// NewDecoder implements Interface
func (j GoCcyJSON) NewDecoder(reader io.Reader) Decoder {
return goccy_json.NewDecoder(reader)
}

// Indent implements Interface
func (j GoCcyJSON) Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
return goccy_json.Indent(dst, src, prefix, indent)
}

// Marshal converts object as bytes
func Marshal(v interface{}) ([]byte, error) {
return DefaultJSONHandler.Marshal(v)
Expand Down
2 changes: 1 addition & 1 deletion modules/lfs/http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (c *HTTPClient) batch(ctx context.Context, operation string, objects []Poin
err = json.NewDecoder(res.Body).Decode(&response)
if err != nil {
log.Error("Error decoding json: %v", err)
return nil, err
return nil, fmt.Errorf("invalid json: %w", err)
}

if len(response.Transfer) == 0 {
Expand Down
2 changes: 2 additions & 0 deletions modules/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,8 @@ func loadFromConf(allowEmpty bool, extraConfig string) {

Cfg.NameMapper = ini.SnackCase

json.SelectDefaultJSONHandler(Cfg.Section("").Key("JSON_LIBRARY").MustString(json.DefaultJSONHandlerType))

homeDir, err := com.HomeDir()
if err != nil {
log.Fatal("Failed to get home directory: %v", err)
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2623,6 +2623,7 @@ config.offline_mode = Local Mode
config.disable_router_log = Disable Router Log
config.run_user = Run As Username
config.run_mode = Run Mode
config.json_library = JSON library
config.git_version = Git Version
config.repo_root_path = Repository Root Path
config.lfs_root_path = LFS Root Path
Expand Down
1 change: 1 addition & 0 deletions routers/web/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ func Config(ctx *context.Context) {
ctx.Data["DisableRouterLog"] = setting.DisableRouterLog
ctx.Data["EnableXORMLog"] = setting.EnableXORMLog
ctx.Data["LogSQL"] = setting.Database.LogSQL
ctx.Data["JSONLibrary"] = json.DefaultJSONHandlerType

ctx.HTML(http.StatusOK, tplConfig)
}
Expand Down
2 changes: 2 additions & 0 deletions templates/admin/config.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
<dd>{{.RunUser}}</dd>
<dt>{{.i18n.Tr "admin.config.run_mode"}}</dt>
<dd>{{.RunMode}}</dd>
<dt>{{.i18n.Tr "admin.config.json_library"}}</dt>
<dd>{{.JSONLibrary}}</dd>

<div class="ui divider"></div>

Expand Down