#json文件增加注释支持

json 当配置文件时,描述清晰,规范,通用,各种好处

尾后逗号 (有时叫做“终止逗号”)在向 JavaScript 代码添加元素、参数、属性时十分有用。如果你想要添加新的属性,并且上一行已经使用了尾后逗号,你可以仅仅添加新的一行,而不需要修改上一行。这使得版本控制的代码比较(diff)更加清晰,代码编辑过程中遇到的麻烦更少

// 行注释

/* */ 块注释

在线测试例子

package main

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/DisposaBoy/JsonConfigReader"
)

func main() {
	var v interface{}
	str := strings.NewReader(`
		{
		// nihao
			"url": "https://www.reim.xyz",
			"authors": [
				"yeluo",
				"qiuzhi"
			], //尾后逗号与注释
		}
	`)
	// wrap our reader before passing it to the json decoder
	r := JsonConfigReader.New(str)
	json.NewDecoder(r).Decode(&v)
	fmt.Println(v)
}

源码就一个文件 github.com/DisposaBoy/JsonConfigReader

package JsonConfigReader

import (
	"bytes"
	"io"
)

type state struct {
	r  io.Reader
	br *bytes.Reader
}

func isNL(c byte) bool {
	return c == '\n' || c == '\r'
}

func isWS(c byte) bool {
	return c == ' ' || c == '\t' || isNL(c)
}

func consumeComment(s []byte, i int) int {
	if i < len(s) && s[i] == '/' {
		s[i-1] = ' '
		for ; i < len(s) && !isNL(s[i]); i += 1 {
			s[i] = ' '
		}
	}
	if i < len(s) && s[i] == '*' {
		s[i-1] = ' '
		s[i] = ' '
		for ; i < len(s); i += 1 {
			if s[i] != '*' {
				s[i] = ' '
			} else {
				s[i] = ' '
				i++
				if i < len(s) {
					if s[i] == '/' {
						s[i] = ' '
						break
					}
				}
			}
		}
	}
	return i
}

func prep(r io.Reader) (s []byte, err error) {
	buf := &bytes.Buffer{}
	_, err = io.Copy(buf, r)
	s = buf.Bytes()
	if err != nil {
		return
	}

	i := 0
	for i < len(s) {
		switch s[i] {
		case '"':
			i += 1
			for i < len(s) {
				if s[i] == '"' {
					i += 1
					break
				} else if s[i] == '\\' {
					i += 1
				}
				i += 1
			}
		case '/':
			i = consumeComment(s, i+1) // i+1 传入
		case ',':
			j := i
			for {
				i += 1
				if i >= len(s) {
					break
				} else if s[i] == '}' || s[i] == ']' {
					s[j] = ' '
					break
				} else if s[i] == '/' {
					i = consumeComment(s, i+1)
				} else if !isWS(s[i]) {
					break
				}
			}
		default:
			i += 1
		}
	}
	return
}

// Read acts as a proxy for the underlying reader and cleans p
// of comments and trailing commas preceeding ] and }
// comments are delimitted by // up until the end the line
func (st *state) Read(p []byte) (n int, err error) {
	if st.br == nil {
		var s []byte
		if s, err = prep(st.r); err != nil {
			return
		}
		st.br = bytes.NewReader(s)
	}
	return st.br.Read(p)
}

// New returns an io.Reader acting as proxy to r
func New(r io.Reader) io.Reader {
	return &state{r: r}
}

字符串处理,挺有意思,可以当面试题了。

参考


#评论

#评论 1 · 2023-04-07T06:55:07.905000Z

鸭子模式 是什么?