提交 def803f1 编写于 作者: N Nick Guerrera

Remove dependency on JsonDataContractSerializer

上级 4be251ed
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
namespace Roslyn.Utilities
{
......@@ -19,7 +20,6 @@ namespace Roslyn.Utilities
internal sealed class JsonWriter : IDisposable
{
private readonly StreamWriter _outptut;
private readonly DataContractJsonSerializer _stringWriter;
private int _indent;
private string _pending;
......@@ -31,7 +31,6 @@ internal sealed class JsonWriter : IDisposable
public JsonWriter(StreamWriter output)
{
_outptut = output;
_stringWriter = new DataContractJsonSerializer(typeof(string));
_pending = "";
}
......@@ -94,15 +93,10 @@ public void Write(string key, bool value)
public void Write(string value)
{
// Consider switching to custom escaping logic here. Flushing all the time (in
// order to borrow DataContractJsonSerializer escaping) is expensive.
//
// Also, it would be nicer not to escape the forward slashes in URIs (which is
// optional in JSON.)
WritePending();
_outptut.Flush();
_stringWriter.WriteObject(_outptut.BaseStream, value);
_outptut.Write('"');
_outptut.Write(EscapeString(value));
_outptut.Write('"');
_pending = s_commaNewLine;
}
......@@ -154,5 +148,108 @@ public void Dispose()
{
_outptut.Dispose();
}
// String escaping implementation forked from System.Runtime.Serialization.Json to
// avoid a large dependency graph for this small amount of code:
//
// https://github.com/dotnet/corefx/blob/master/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JavaScriptString.cs
//
// Possible future improvements: https://github.com/dotnet/roslyn/issues/9769
//
// - Avoid intermediate StringBuilder and send escaped output directly to the destination.
//
// - Stop escaping '/': it is is optional per JSON spec and several users have expressed
// that they don't like the way '\/' looks.
//
private static string EscapeString(string value)
{
StringBuilder b = null;
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
int startIndex = 0;
int count = 0;
for (int i = 0; i < value.Length; i++)
{
char c = value[i];
if (c == '\"' || c == '\'' || c == '/' || c == '\\' || ShouldAppendAsUnicode(c))
{
if (b == null)
{
b = new StringBuilder(value.Length + 5);
}
if (count > 0)
{
b.Append(value, startIndex, count);
}
startIndex = i + 1;
count = 0;
}
switch (c)
{
case '\"':
b.Append("\\\"");
break;
case '\\':
b.Append("\\\\");
break;
case '/':
b.Append("\\/");
break;
case '\'':
b.Append("\'");
break;
default:
if (ShouldAppendAsUnicode(c))
{
AppendCharAsUnicode(b, c);
}
else
{
count++;
}
break;
}
}
if (b == null)
{
return value;
}
if (count > 0)
{
b.Append(value, startIndex, count);
}
return b.ToString();
}
private static void AppendCharAsUnicode(StringBuilder builder, char c)
{
builder.Append("\\u");
builder.AppendFormat(CultureInfo.InvariantCulture, "{0:x4}", (int)c);
}
private static bool ShouldAppendAsUnicode(char c)
{
// Note on newline characters: Newline characters in JSON strings need to be encoded on the way out
// See Unicode 6.2, Table 5-1 (http://www.unicode.org/versions/Unicode6.2.0/ch05.pdf]) for the full list.
// We only care about NEL, LS, and PS, since the other newline characters are all
// control characters so are already encoded.
return c < ' ' ||
c >= (char)0xfffe || // max char
(c >= (char)0xd800 && c <= (char)0xdfff) || // between high and low surrogate
(c == '\u0085' || c == '\u2028' || c == '\u2029'); // Unicode new line characters
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册