mirror of https://github.com/icsharpcode/ILSpy.git
3 changed files with 0 additions and 448 deletions
@ -1,97 +0,0 @@ |
|||||||
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
|
||||||
|
|
||||||
namespace LightJson.Serialization |
|
||||||
{ |
|
||||||
using System; |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The exception that is thrown when a JSON value cannot be serialized.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// This exception is only intended to be thrown by LightJson.
|
|
||||||
/// </remarks>
|
|
||||||
internal sealed class JsonSerializationException : Exception |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="JsonSerializationException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public JsonSerializationException() |
|
||||||
: base(GetDefaultMessage(ErrorType.Unknown)) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="JsonSerializationException"/> class with the given error type.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">The error type that describes the cause of the error.</param>
|
|
||||||
public JsonSerializationException(ErrorType type) |
|
||||||
: this(GetDefaultMessage(type), type) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="JsonSerializationException"/> class with the given message and
|
|
||||||
/// error type.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
/// <param name="type">The error type that describes the cause of the error.</param>
|
|
||||||
public JsonSerializationException(string message, ErrorType type) |
|
||||||
: base(message) |
|
||||||
{ |
|
||||||
this.Type = type; |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enumerates the types of errors that can occur during serialization.
|
|
||||||
/// </summary>
|
|
||||||
public enum ErrorType |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Indicates that the cause of the error is unknown.
|
|
||||||
/// </summary>
|
|
||||||
Unknown = 0, |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates that the writer encountered an invalid number value (NAN, infinity) during serialization.
|
|
||||||
/// </summary>
|
|
||||||
InvalidNumber, |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates that the object been serialized contains an invalid JSON value type.
|
|
||||||
/// That is, a value type that is not null, boolean, number, string, object, or array.
|
|
||||||
/// </summary>
|
|
||||||
InvalidValueType, |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates that the object been serialized contains a circular reference.
|
|
||||||
/// </summary>
|
|
||||||
CircularReference, |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the type of error that caused the exception to be thrown.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>
|
|
||||||
/// The type of error that caused the exception to be thrown.
|
|
||||||
/// </value>
|
|
||||||
public ErrorType Type { get; } |
|
||||||
|
|
||||||
private static string GetDefaultMessage(ErrorType type) |
|
||||||
{ |
|
||||||
switch (type) { |
|
||||||
case ErrorType.InvalidNumber: |
|
||||||
return "The value been serialized contains an invalid number value (NAN, infinity)."; |
|
||||||
|
|
||||||
case ErrorType.InvalidValueType: |
|
||||||
return "The value been serialized contains (or is) an invalid JSON type."; |
|
||||||
|
|
||||||
case ErrorType.CircularReference: |
|
||||||
return "The value been serialized contains circular references."; |
|
||||||
|
|
||||||
default: |
|
||||||
return "An error occurred during serialization."; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,349 +0,0 @@ |
|||||||
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
|
||||||
|
|
||||||
namespace LightJson.Serialization |
|
||||||
{ |
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Diagnostics; |
|
||||||
using System.Globalization; |
|
||||||
using System.IO; |
|
||||||
using ErrorType = JsonSerializationException.ErrorType; |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a writer that can write string representations of JsonValues.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class JsonWriter : IDisposable |
|
||||||
{ |
|
||||||
private int indent; |
|
||||||
private bool isNewLine; |
|
||||||
private TextWriter writer; |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A set of containing all the collection objects (JsonObject/JsonArray) being rendered.
|
|
||||||
/// It is used to prevent circular references; since collections that contain themselves
|
|
||||||
/// will never finish rendering.
|
|
||||||
/// </summary>
|
|
||||||
private HashSet<IEnumerable<JsonValue>> renderingCollections; |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="JsonWriter"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public JsonWriter() |
|
||||||
: this(false) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="JsonWriter"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pretty">
|
|
||||||
/// A value indicating whether the output of the writer should be human-readable.
|
|
||||||
/// </param>
|
|
||||||
public JsonWriter(bool pretty) |
|
||||||
{ |
|
||||||
if (pretty) { |
|
||||||
this.IndentString = "\t"; |
|
||||||
this.SpacingString = " "; |
|
||||||
this.NewLineString = "\n"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the string representing a indent in the output.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>
|
|
||||||
/// The string representing a indent in the output.
|
|
||||||
/// </value>
|
|
||||||
public string IndentString { get; set; } |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the string representing a space in the output.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>
|
|
||||||
/// The string representing a space in the output.
|
|
||||||
/// </value>
|
|
||||||
public string SpacingString { get; set; } |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the string representing a new line on the output.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>
|
|
||||||
/// The string representing a new line on the output.
|
|
||||||
/// </value>
|
|
||||||
public string NewLineString { get; set; } |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether JsonObject properties should be written in a deterministic order.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>
|
|
||||||
/// A value indicating whether JsonObject properties should be written in a deterministic order.
|
|
||||||
/// </value>
|
|
||||||
public bool SortObjects { get; set; } |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a string representation of the given JsonValue.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="jsonValue">The JsonValue to serialize.</param>
|
|
||||||
/// <returns>The serialized value.</returns>
|
|
||||||
public string Serialize(JsonValue jsonValue) |
|
||||||
{ |
|
||||||
this.Initialize(); |
|
||||||
|
|
||||||
this.Render(jsonValue); |
|
||||||
|
|
||||||
return this.writer.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Releases all the resources used by this object.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose() |
|
||||||
{ |
|
||||||
if (this.writer != null) { |
|
||||||
this.writer.Dispose(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private static bool IsValidNumber(double number) |
|
||||||
{ |
|
||||||
return !(double.IsNaN(number) || double.IsInfinity(number)); |
|
||||||
} |
|
||||||
|
|
||||||
private void Initialize() |
|
||||||
{ |
|
||||||
this.indent = 0; |
|
||||||
this.isNewLine = true; |
|
||||||
this.writer = new StringWriter(); |
|
||||||
this.renderingCollections = new HashSet<IEnumerable<JsonValue>>(); |
|
||||||
} |
|
||||||
|
|
||||||
private void Write(string text) |
|
||||||
{ |
|
||||||
if (this.isNewLine) { |
|
||||||
this.isNewLine = false; |
|
||||||
this.WriteIndentation(); |
|
||||||
} |
|
||||||
|
|
||||||
this.writer.Write(text); |
|
||||||
} |
|
||||||
|
|
||||||
private void WriteEncodedJsonValue(JsonValue value) |
|
||||||
{ |
|
||||||
switch (value.Type) { |
|
||||||
case JsonValueType.Null: |
|
||||||
this.Write("null"); |
|
||||||
break; |
|
||||||
|
|
||||||
case JsonValueType.Boolean: |
|
||||||
this.Write(value.AsString); |
|
||||||
break; |
|
||||||
|
|
||||||
case JsonValueType.Number: |
|
||||||
this.Write(((double)value).ToString(CultureInfo.InvariantCulture)); |
|
||||||
break; |
|
||||||
|
|
||||||
default: |
|
||||||
Debug.Assert(value.Type == JsonValueType.String, "value.Type == JsonValueType.String"); |
|
||||||
this.WriteEncodedString((string)value); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void WriteEncodedString(string text) |
|
||||||
{ |
|
||||||
this.Write("\""); |
|
||||||
|
|
||||||
for (int i = 0; i < text.Length; i += 1) { |
|
||||||
var currentChar = text[i]; |
|
||||||
|
|
||||||
// Encoding special characters.
|
|
||||||
switch (currentChar) { |
|
||||||
case '\\': |
|
||||||
this.writer.Write("\\\\"); |
|
||||||
break; |
|
||||||
|
|
||||||
case '\"': |
|
||||||
this.writer.Write("\\\""); |
|
||||||
break; |
|
||||||
|
|
||||||
case '/': |
|
||||||
this.writer.Write("\\/"); |
|
||||||
break; |
|
||||||
|
|
||||||
case '\b': |
|
||||||
this.writer.Write("\\b"); |
|
||||||
break; |
|
||||||
|
|
||||||
case '\f': |
|
||||||
this.writer.Write("\\f"); |
|
||||||
break; |
|
||||||
|
|
||||||
case '\n': |
|
||||||
this.writer.Write("\\n"); |
|
||||||
break; |
|
||||||
|
|
||||||
case '\r': |
|
||||||
this.writer.Write("\\r"); |
|
||||||
break; |
|
||||||
|
|
||||||
case '\t': |
|
||||||
this.writer.Write("\\t"); |
|
||||||
break; |
|
||||||
|
|
||||||
default: |
|
||||||
this.writer.Write(currentChar); |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
this.writer.Write("\""); |
|
||||||
} |
|
||||||
|
|
||||||
private void WriteIndentation() |
|
||||||
{ |
|
||||||
for (var i = 0; i < this.indent; i += 1) { |
|
||||||
this.Write(this.IndentString); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void WriteSpacing() |
|
||||||
{ |
|
||||||
this.Write(this.SpacingString); |
|
||||||
} |
|
||||||
|
|
||||||
private void WriteLine() |
|
||||||
{ |
|
||||||
this.Write(this.NewLineString); |
|
||||||
this.isNewLine = true; |
|
||||||
} |
|
||||||
|
|
||||||
private void WriteLine(string line) |
|
||||||
{ |
|
||||||
this.Write(line); |
|
||||||
this.WriteLine(); |
|
||||||
} |
|
||||||
|
|
||||||
private void AddRenderingCollection(IEnumerable<JsonValue> value) |
|
||||||
{ |
|
||||||
if (!this.renderingCollections.Add(value)) { |
|
||||||
throw new JsonSerializationException(ErrorType.CircularReference); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void RemoveRenderingCollection(IEnumerable<JsonValue> value) |
|
||||||
{ |
|
||||||
this.renderingCollections.Remove(value); |
|
||||||
} |
|
||||||
|
|
||||||
private void Render(JsonValue value) |
|
||||||
{ |
|
||||||
switch (value.Type) { |
|
||||||
case JsonValueType.Null: |
|
||||||
case JsonValueType.Boolean: |
|
||||||
case JsonValueType.Number: |
|
||||||
case JsonValueType.String: |
|
||||||
this.WriteEncodedJsonValue(value); |
|
||||||
break; |
|
||||||
|
|
||||||
case JsonValueType.Object: |
|
||||||
this.Render((JsonObject)value); |
|
||||||
break; |
|
||||||
|
|
||||||
case JsonValueType.Array: |
|
||||||
this.Render((JsonArray)value); |
|
||||||
break; |
|
||||||
|
|
||||||
default: |
|
||||||
throw new JsonSerializationException(ErrorType.InvalidValueType); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void Render(JsonArray value) |
|
||||||
{ |
|
||||||
this.AddRenderingCollection(value); |
|
||||||
|
|
||||||
this.WriteLine("["); |
|
||||||
|
|
||||||
this.indent += 1; |
|
||||||
|
|
||||||
using (var enumerator = value.GetEnumerator()) { |
|
||||||
var hasNext = enumerator.MoveNext(); |
|
||||||
|
|
||||||
while (hasNext) { |
|
||||||
this.Render(enumerator.Current); |
|
||||||
|
|
||||||
hasNext = enumerator.MoveNext(); |
|
||||||
|
|
||||||
if (hasNext) { |
|
||||||
this.WriteLine(","); |
|
||||||
} else { |
|
||||||
this.WriteLine(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
this.indent -= 1; |
|
||||||
|
|
||||||
this.Write("]"); |
|
||||||
|
|
||||||
this.RemoveRenderingCollection(value); |
|
||||||
} |
|
||||||
|
|
||||||
private void Render(JsonObject value) |
|
||||||
{ |
|
||||||
this.AddRenderingCollection(value); |
|
||||||
|
|
||||||
this.WriteLine("{"); |
|
||||||
|
|
||||||
this.indent += 1; |
|
||||||
|
|
||||||
using (var enumerator = this.GetJsonObjectEnumerator(value)) { |
|
||||||
var hasNext = enumerator.MoveNext(); |
|
||||||
|
|
||||||
while (hasNext) { |
|
||||||
this.WriteEncodedString(enumerator.Current.Key); |
|
||||||
this.Write(":"); |
|
||||||
this.WriteSpacing(); |
|
||||||
this.Render(enumerator.Current.Value); |
|
||||||
|
|
||||||
hasNext = enumerator.MoveNext(); |
|
||||||
|
|
||||||
if (hasNext) { |
|
||||||
this.WriteLine(","); |
|
||||||
} else { |
|
||||||
this.WriteLine(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
this.indent -= 1; |
|
||||||
|
|
||||||
this.Write("}"); |
|
||||||
|
|
||||||
this.RemoveRenderingCollection(value); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets an JsonObject enumerator based on the configuration of this JsonWriter.
|
|
||||||
/// If JsonWriter.SortObjects is set to true, then a ordered enumerator is returned.
|
|
||||||
/// Otherwise, a faster non-deterministic enumerator is returned.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="jsonObject">The JsonObject for which to get an enumerator.</param>
|
|
||||||
/// <returns>An enumerator for the properties in a <see cref="JsonObject"/>.</returns>
|
|
||||||
private IEnumerator<KeyValuePair<string, JsonValue>> GetJsonObjectEnumerator(JsonObject jsonObject) |
|
||||||
{ |
|
||||||
if (this.SortObjects) { |
|
||||||
var sortedDictionary = new SortedDictionary<string, JsonValue>(StringComparer.Ordinal); |
|
||||||
|
|
||||||
foreach (var item in jsonObject) { |
|
||||||
sortedDictionary.Add(item.Key, item.Value); |
|
||||||
} |
|
||||||
|
|
||||||
return sortedDictionary.GetEnumerator(); |
|
||||||
} else { |
|
||||||
return jsonObject.GetEnumerator(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue