json.go raw
1 package helpers
2
3 // Minimal JSON serialization for Nostr events.
4 // No encoding/json dependency.
5
6 // JsonString returns a JSON-escaped string with surrounding quotes.
7 // Uses string concat to preserve non-ASCII in tinyjs.
8 func JsonString(s string) string {
9 result := "\""
10 start := 0
11 for i := 0; i < len(s); i++ {
12 c := s[i]
13 var esc string
14 switch c {
15 case '"':
16 esc = "\\\""
17 case '\\':
18 esc = "\\\\"
19 case '\n':
20 esc = "\\n"
21 case '\r':
22 esc = "\\r"
23 case '\t':
24 esc = "\\t"
25 case '\b':
26 esc = "\\b"
27 case '\f':
28 esc = "\\f"
29 default:
30 if c < 0x20 {
31 esc = "\\u00" + string(hexChars[c>>4]) + string(hexChars[c&0x0f])
32 } else {
33 continue
34 }
35 }
36 result += s[start:i] + esc
37 start = i + 1
38 }
39 return result + s[start:] + "\""
40 }
41
42 // JsonGetString extracts a string value for the given key from a JSON object.
43 // Returns empty string if not found. Handles basic escape sequences.
44 // Uses string concat (not []byte) to preserve non-ASCII characters in tinyjs.
45 func JsonGetString(s, key string) string {
46 kq := "\"" + key + "\""
47 kqLen := len(kq)
48 for i := 0; i <= len(s)-kqLen; i++ {
49 if s[i:i+kqLen] == kq {
50 j := i + kqLen
51 for j < len(s) && (s[j] == ' ' || s[j] == '\t' || s[j] == '\n' || s[j] == '\r') {
52 j++
53 }
54 if j >= len(s) || s[j] != ':' {
55 continue
56 }
57 j++
58 for j < len(s) && (s[j] == ' ' || s[j] == '\t' || s[j] == '\n' || s[j] == '\r') {
59 j++
60 }
61 if j >= len(s) || s[j] != '"' {
62 continue
63 }
64 j++
65 start := j
66 result := ""
67 for j < len(s) {
68 if s[j] == '\\' && j+1 < len(s) {
69 result += s[start:j]
70 j++
71 switch s[j] {
72 case '"', '\\', '/':
73 result += s[j : j+1]
74 case 'n':
75 result += "\n"
76 case 'r':
77 result += "\r"
78 case 't':
79 result += "\t"
80 default:
81 result += s[j : j+1]
82 }
83 j++
84 start = j
85 continue
86 }
87 if s[j] == '"' {
88 return result + s[start:j]
89 }
90 j++
91 }
92 }
93 }
94 return ""
95 }
96
97 // Itoa converts int64 to decimal string.
98 func Itoa(n int64) string {
99 if n == 0 {
100 return "0"
101 }
102 neg := false
103 if n < 0 {
104 neg = true
105 n = -n
106 }
107 var buf [20]byte
108 i := len(buf)
109 for n > 0 {
110 i--
111 buf[i] = byte('0' + n%10)
112 n /= 10
113 }
114 if neg {
115 i--
116 buf[i] = '-'
117 }
118 return string(buf[i:])
119 }
120