I need to decode and encode strings using the gson format (it's a json dialect). Below is the code I came up with so far translated from the gson(Java) library
For some reasons none of the characters I try to decode/replace is actually replaced. I believe I'm doing something wrong with the character escaping(I'm new to go) so any direction/help to fix it would be appreciated.
Go Playground
package main
import (
"bytes"
"fmt"
"strings"
)
const s = `https:\/\/exampple.com\/static\/_\/js\/k\x3dgaia.gaiafe_glif.en.nnMHsIffkD4.O\/m\x3dglifb,identifier,unknownerror\/am\x3dggIgAAAAAAEKBCEImA2CYiCxoQo\/rt\x3dj\/d\x3d1\/rs\x3dABkqax3Fc8CWFtgWOYXlvHJI_bE3oVSwgA`
const des = `https://exampple.com/static/_/js/k=gaia.gaiafe_glif.en.nnMHsIffkD4.O/m=P9M9H,HUb4Ab,sy1m,sy1n,emo,sy1k,sy54,gsfs7c/am=ggIgAAAAAAEKBCEImA2CYiCxoQo/rt=j/d=0/rs=ABkqax3Fc8CWFtgWOYXlvHJI_bE3oVSwgA`
func main() {
dec, err := Decode(s, true)
if err != nil {
panic(err)
}
if dec != des {
fmt.Printf("expected
%v
got
%s", dec, des)
}
}
type replacementChar map[rune]string
func (r replacementChar) get(k rune) string {
return fmt.Sprintf("\\u%04x", r[k])
}
var replacement = replacementChar{
'"': "\\\"",
'\\': "\\\\",
'\t': "\\t",
'\b': "\\b",
'
': "\
",
'': "\",
'\f': "\\f",
}
var htmlReplacement = replacementChar{
'<': "\\u003c",
'>': "\\u003e",
'&': "\\u0026",
'=': "\\u003d",
'\'': "\\u0027",
}
var extraReplacement = replacementChar{
'\u2028': "\\u2028",
'\u2029': "\\u2029",
}
/*
* From RFC 7159, "All Unicode characters may be placed within the
* quotation marks except for the characters that must be escaped:
* quotation mark, reverse solidus, and the control characters
* (U+0000 through U+001F)."
*
* We also escape '\u2028' and '\u2029', which JavaScript interprets as
* newline characters. This prevents eval() from failing with a syntax
* error. http://code.google.com/p/google-gson/issues/detail?id=341
*/
func Encode(s string, htmlSafe bool) (string, error) {
buf := bytes.NewBuffer([]byte("\""))
var err error
for _, r := range s {
switch {
case replacement[r] != "":
_, err = buf.WriteString(replacement.get(r))
if err != nil {
return "", err
}
case htmlSafe && htmlReplacement[r] != "":
_, err = buf.WriteString(htmlReplacement.get(r))
if err != nil {
return "", err
}
case extraReplacement[r] != "":
_, err = buf.WriteString(extraReplacement.get(r))
if err != nil {
return "", err
}
default:
_, err = buf.WriteRune(r)
if err != nil {
return "", err
}
}
}
buf.WriteString("\"")
return buf.String(), nil
}
var decodeHTMLReplacementPair []string
var decodeReplacementPair []string
var decodeReplacementAll []string
func init() {
for k, _ := range htmlReplacement {
decodeHTMLReplacementPair = append(decodeHTMLReplacementPair, htmlReplacement.get(k))
decodeHTMLReplacementPair = append(decodeHTMLReplacementPair, string(k))
}
for k, _ := range replacement {
decodeReplacementPair = append(decodeReplacementPair, replacement.get(k))
decodeReplacementPair = append(decodeReplacementPair, string(k))
}
for k, _ := range extraReplacement {
decodeReplacementPair = append(decodeReplacementPair, extraReplacement.get(k))
decodeReplacementPair = append(decodeReplacementPair, string(k))
decodeHTMLReplacementPair = append(decodeHTMLReplacementPair, extraReplacement.get(k))
decodeHTMLReplacementPair = append(decodeHTMLReplacementPair, string(k))
}
decodeReplacementAll = append(decodeHTMLReplacementPair, decodeReplacementPair...)
}
func Decode(s string, htmlSafe bool) (string, error) {
var r *strings.Replacer
if !htmlSafe {
r = strings.NewReplacer(decodeHTMLReplacementPair...)
} else {
r = strings.NewReplacer(decodeReplacementAll...)
}
return r.Replace(s), nil
}
/* Original Java Source https://github.com/google/gson/blob/master/gson/src/main/java/com/google/gson/stream/JsonWriter.java
private static final String[] REPLACEMENT_CHARS;
private static final String[] HTML_SAFE_REPLACEMENT_CHARS;
static {
REPLACEMENT_CHARS = new String[128];
for (int i = 0; i <= 0x1f; i++) {
REPLACEMENT_CHARS[i] = String.format("\\u%04x", (int) i);
}
REPLACEMENT_CHARS['"'] = "\\\"";
REPLACEMENT_CHARS['\\'] = "\\\\";
REPLACEMENT_CHARS['\t'] = "\\t";
REPLACEMENT_CHARS['\b'] = "\\b";
REPLACEMENT_CHARS['
'] = "\
";
REPLACEMENT_CHARS[''] = "\";
REPLACEMENT_CHARS['\f'] = "\\f";
HTML_SAFE_REPLACEMENT_CHARS = REPLACEMENT_CHARS.clone();
HTML_SAFE_REPLACEMENT_CHARS['<'] = "\\u003c";
HTML_SAFE_REPLACEMENT_CHARS['>'] = "\\u003e";
HTML_SAFE_REPLACEMENT_CHARS['&'] = "\\u0026";
HTML_SAFE_REPLACEMENT_CHARS['='] = "\\u003d";
HTML_SAFE_REPLACEMENT_CHARS['\''] = "\\u0027";
}
private void string(String value) throws IOException {
String[] replacements = htmlSafe ? HTML_SAFE_REPLACEMENT_CHARS : REPLACEMENT_CHARS;
out.write("\"");
int last = 0;
int length = value.length();
for (int i = 0; i < length; i++) {
char c = value.charAt(i);
String replacement;
if (c < 128) {
replacement = replacements[c];
if (replacement == null) {
continue;
}
} else if (c == '\u2028') {
replacement = "\\u2028";
} else if (c == '\u2029') {
replacement = "\\u2029";
} else {
continue;
}
if (last < i) {
out.write(value, last, i - last);
}
out.write(replacement);
last = i + 1;
}
if (last < length) {
out.write(value, last, length - last);
}
out.write("\"");
}
*/