diff --git a/orderedmap.go b/orderedmap.go index 61587d9..8ac17a6 100644 --- a/orderedmap.go +++ b/orderedmap.go @@ -242,24 +242,40 @@ func decodeSlice(dec *json.Decoder, s []interface{}, escapeHTML bool) error { } } +func encodeNoNewline(v interface{}, escapeHTML bool) ([]byte, error) { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + enc.SetEscapeHTML(escapeHTML) + if err := enc.Encode(v); err != nil { + return nil, err + } + // 末尾の改行('\n')を削除 + data := buf.Bytes() + if len(data) > 0 && data[len(data)-1] == '\n' { + data = data[:len(data)-1] + } + return data, nil +} + func (o OrderedMap) MarshalJSON() ([]byte, error) { var buf bytes.Buffer buf.WriteByte('{') - encoder := json.NewEncoder(&buf) - encoder.SetEscapeHTML(o.escapeHTML) for i, k := range o.keys { if i > 0 { buf.WriteByte(',') } - // add key - if err := encoder.Encode(k); err != nil { + keyBytes, err := encodeNoNewline(k, o.escapeHTML) + if err != nil { return nil, err } + buf.Write(keyBytes) buf.WriteByte(':') - // add value - if err := encoder.Encode(o.values[k]); err != nil { + + valueBytes, err := encodeNoNewline(o.values[k], o.escapeHTML) + if err != nil { return nil, err } + buf.Write(valueBytes) } buf.WriteByte('}') return buf.Bytes(), nil diff --git a/orderedmap_test.go b/orderedmap_test.go index 5b89ef6..6e895c2 100644 --- a/orderedmap_test.go +++ b/orderedmap_test.go @@ -69,10 +69,10 @@ func TestOrderedMap(t *testing.T) { // Values method values := o.Values() expectedValues := map[string]interface{}{ - "number": 4, - "string": "x", + "number": 4, + "string": "x", "strings": []string{"t", "u"}, - "mixed": []interface{}{ 1, "1" }, + "mixed": []interface{}{1, "1"}, } if !reflect.DeepEqual(values, expectedValues) { t.Error("Values method returned unexpected map") @@ -595,3 +595,29 @@ func TestOrderedMap_empty_map(t *testing.T) { t.Error("Got", marshalledStr) } } + +func TestEncodeNoNewline(t *testing.T) { + tests := []struct { + input interface{} + escapeHTML bool + expected string + }{ + {"test", true, "\"test\""}, + {"<>&", false, "\"<>&\""}, + {"<>&", true, "\"\\u003c\\u003e\\u0026\""}, + {123, true, "123"}, + } + + for _, tt := range tests { + b, err := encodeNoNewline(tt.input, tt.escapeHTML) + if err != nil { + t.Errorf("encodeNoNewline error: %v", err) + } + if len(b) > 0 && b[len(b)-1] == '\n' { + t.Errorf("encodeNoNewline output ends with newline: %q", string(b)) + } + if string(b) != tt.expected { + t.Errorf("For input %v with escapeHTML=%v: expected %q, got %q", tt.input, tt.escapeHTML, tt.expected, string(b)) + } + } +}