2
using System.Collections;
3
using System.Collections.Generic;
6
using ServiceStack.Text.Json;
7
using ServiceStack.Text.Jsv;
9
namespace ServiceStack.Text.Common
11
public static class JsWriter
13
public const string TypeAttr = "__type";
15
public const char MapStartChar = '{';
16
public const char MapKeySeperator = ':';
17
public const char ItemSeperator = ',';
18
public const char MapEndChar = '}';
19
public const string MapNullValue = "\"\"";
20
public const string EmptyMap = "{}";
22
public const char ListStartChar = '[';
23
public const char ListEndChar = ']';
24
public const char ReturnChar = '\r';
25
public const char LineFeedChar = '\n';
27
public const char QuoteChar = '"';
28
public const string QuoteString = "\"";
29
public const string EscapedQuoteString = "\\\"";
30
public const string ItemSeperatorString = ",";
31
public const string MapKeySeperatorString = ":";
33
public static readonly char[] CsvChars = new[] { ItemSeperator, QuoteChar };
34
public static readonly char[] EscapeChars = new[] { QuoteChar, MapKeySeperator, ItemSeperator, MapStartChar, MapEndChar, ListStartChar, ListEndChar, ReturnChar, LineFeedChar };
36
private const int LengthFromLargestChar = '}' + 1;
37
private static readonly bool[] EscapeCharFlags = new bool[LengthFromLargestChar];
41
foreach (var escapeChar in EscapeChars)
43
EscapeCharFlags[escapeChar] = true;
45
var loadConfig = JsConfig.IncludeNullValues;
48
public static void WriteDynamic(Action callback)
50
JsState.IsWritingDynamic = true;
57
JsState.IsWritingDynamic = false;
62
/// micro optimizations: using flags instead of value.IndexOfAny(EscapeChars)
64
/// <param name="value"></param>
65
/// <returns></returns>
66
public static bool HasAnyEscapeChars(string value)
68
var len = value.Length;
69
for (var i = 0; i < len; i++)
72
if (c >= LengthFromLargestChar || !EscapeCharFlags[c]) continue;
78
internal static void WriteItemSeperatorIfRanOnce(TextWriter writer, ref bool ranOnce)
81
writer.Write(ItemSeperator);
85
foreach (var escapeChar in EscapeChars)
87
EscapeCharFlags[escapeChar] = true;
91
internal static bool ShouldUseDefaultToStringMethod(Type type)
93
return type == typeof(byte) || type == typeof(byte?)
94
|| type == typeof(short) || type == typeof(short?)
95
|| type == typeof(ushort) || type == typeof(ushort?)
96
|| type == typeof(int) || type == typeof(int?)
97
|| type == typeof(uint) || type == typeof(uint?)
98
|| type == typeof(long) || type == typeof(long?)
99
|| type == typeof(ulong) || type == typeof(ulong?)
100
|| type == typeof(bool) || type == typeof(bool?)
101
|| type == typeof(DateTime) || type == typeof(DateTime?)
102
|| type == typeof(Guid) || type == typeof(Guid?)
103
|| type == typeof(float) || type == typeof(float?)
104
|| type == typeof(double) || type == typeof(double?)
105
|| type == typeof(decimal) || type == typeof(decimal?);
108
internal static ITypeSerializer GetTypeSerializer<TSerializer>()
110
if (typeof(TSerializer) == typeof(JsvTypeSerializer))
111
return JsvTypeSerializer.Instance;
113
if (typeof(TSerializer) == typeof(JsonTypeSerializer))
114
return JsonTypeSerializer.Instance;
116
throw new NotSupportedException(typeof(TSerializer).Name);
120
internal class JsWriter<TSerializer>
121
where TSerializer : ITypeSerializer
123
private static readonly ITypeSerializer Serializer = JsWriter.GetTypeSerializer<TSerializer>();
127
this.SpecialTypes = new Dictionary<Type, WriteObjectDelegate>
129
{ typeof(Uri), Serializer.WriteObjectString },
130
{ typeof(Type), WriteType },
131
{ typeof(Exception), Serializer.WriteException },
132
#if !MONOTOUCH && !SILVERLIGHT && !XBOX
133
{ typeof(System.Data.Linq.Binary), Serializer.WriteLinqBinary },
138
public WriteObjectDelegate GetValueTypeToStringMethod(Type type)
140
if (type == typeof(char) || type == typeof(char?))
141
return Serializer.WriteChar;
142
if (type == typeof(int) || type == typeof(int?))
143
return Serializer.WriteInt32;
144
if (type == typeof(long) || type == typeof(long?))
145
return Serializer.WriteInt64;
146
if (type == typeof(ulong) || type == typeof(ulong?))
147
return Serializer.WriteUInt64;
148
if (type == typeof(uint) || type == typeof(uint?))
149
return Serializer.WriteUInt32;
151
if (type == typeof(byte) || type == typeof(byte?))
152
return Serializer.WriteByte;
154
if (type == typeof(short) || type == typeof(short?))
155
return Serializer.WriteInt16;
156
if (type == typeof(ushort) || type == typeof(ushort?))
157
return Serializer.WriteUInt16;
159
if (type == typeof(bool) || type == typeof(bool?))
160
return Serializer.WriteBool;
162
if (type == typeof(DateTime))
163
return Serializer.WriteDateTime;
165
if (type == typeof(DateTime?))
166
return Serializer.WriteNullableDateTime;
168
if (type == typeof(Guid))
169
return Serializer.WriteGuid;
171
if (type == typeof(Guid?))
172
return Serializer.WriteNullableGuid;
174
if (type == typeof(float) || type == typeof(float?))
175
return Serializer.WriteFloat;
177
if (type == typeof(double) || type == typeof(double?))
178
return Serializer.WriteDouble;
180
if (type == typeof(decimal) || type == typeof(decimal?))
181
return Serializer.WriteDecimal;
183
if (type.IsEnum || type.UnderlyingSystemType.IsEnum)
184
return type.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0
185
? (WriteObjectDelegate)Serializer.WriteEnumFlags
186
: Serializer.WriteEnum;
188
return Serializer.WriteObjectString;
191
internal WriteObjectDelegate GetWriteFn<T>()
193
if (typeof(T) == typeof(string))
195
return Serializer.WriteObjectString;
198
if (typeof(T).IsValueType)
200
return JsConfig<T>.SerializeFn != null
201
? JsConfig<T>.WriteFn<TSerializer>
202
: GetValueTypeToStringMethod(typeof(T));
205
var specialWriteFn = GetSpecialWriteFn(typeof(T));
206
if (specialWriteFn != null)
208
return specialWriteFn;
211
if (typeof(T).IsArray)
213
if (typeof(T) == typeof(byte[]))
214
return (w, x) => WriteLists.WriteBytes(Serializer, w, x);
216
if (typeof(T) == typeof(string[]))
217
return (w, x) => WriteLists.WriteStringArray(Serializer, w, x);
219
if (typeof(T) == typeof(int[]))
220
return WriteListsOfElements<int, TSerializer>.WriteGenericArrayValueType;
221
if (typeof(T) == typeof(long[]))
222
return WriteListsOfElements<long, TSerializer>.WriteGenericArrayValueType;
224
var elementType = typeof(T).GetElementType();
225
var writeFn = WriteListsOfElements<TSerializer>.GetGenericWriteArray(elementType);
229
if (typeof(T).IsGenericType())
231
if (typeof(T).IsOrHasGenericInterfaceTypeOf(typeof(IList<>)))
232
return WriteLists<T, TSerializer>.Write;
234
var mapInterface = typeof(T).GetTypeWithGenericTypeDefinitionOf(typeof(IDictionary<,>));
235
if (mapInterface != null)
237
var mapTypeArgs = mapInterface.GetGenericArguments();
238
var writeFn = WriteDictionary<TSerializer>.GetWriteGenericDictionary(
239
mapTypeArgs[0], mapTypeArgs[1]);
241
var keyWriteFn = Serializer.GetWriteFn(mapTypeArgs[0]);
242
var valueWriteFn = Serializer.GetWriteFn(mapTypeArgs[1]);
244
return (w, x) => writeFn(w, x, keyWriteFn, valueWriteFn);
247
var enumerableInterface = typeof(T).GetTypeWithGenericTypeDefinitionOf(typeof(IEnumerable<>));
248
if (enumerableInterface != null)
250
var elementType = enumerableInterface.GetGenericArguments()[0];
251
var writeFn = WriteListsOfElements<TSerializer>.GetGenericWriteEnumerable(elementType);
256
var isCollection = typeof(T).IsOrHasGenericInterfaceTypeOf(typeof(ICollection));
259
var isDictionary = typeof(T).IsAssignableFrom(typeof(IDictionary))
260
|| typeof(T).HasInterface(typeof(IDictionary));
263
return WriteDictionary<TSerializer>.WriteIDictionary;
266
return WriteListsOfElements<TSerializer>.WriteIEnumerable;
269
var isEnumerable = typeof(T).IsAssignableFrom(typeof(IEnumerable))
270
|| typeof(T).HasInterface(typeof(IEnumerable));
274
return WriteListsOfElements<TSerializer>.WriteIEnumerable;
277
if (typeof(T).IsClass || typeof(T).IsInterface)
279
var typeToStringMethod = WriteType<T, TSerializer>.Write;
280
if (typeToStringMethod != null)
282
return typeToStringMethod;
286
return Serializer.WriteBuiltIn;
290
public Dictionary<Type, WriteObjectDelegate> SpecialTypes;
292
public WriteObjectDelegate GetSpecialWriteFn(Type type)
294
WriteObjectDelegate writeFn = null;
295
if (SpecialTypes.TryGetValue(type, out writeFn))
298
if (type.IsInstanceOfType(typeof(Type)))
301
if (type.IsInstanceOf(typeof(Exception)))
302
return Serializer.WriteException;
307
public void WriteType(TextWriter writer, object value)
309
Serializer.WriteRawString(writer, ((Type)value).ToTypeString());
b'\\ No newline at end of file'