289 lines
8.8 KiB
C#

using System;
using System.Reflection;
using System.Runtime.Serialization;
using System.Security;
using GameDevWare.Serialization.Serializers;
#pragma warning disable 1591
// ReSharper disable once CheckNamespace
namespace GameDevWare.Serialization
{
[Serializable]
public class JsonSerializationException : SerializationException
{
public enum ErrorCode
{
SerializationException = 1,
EmptyMemberName,
DiscriminatorNotFirstMemberOfObject,
CantCreateInstanceOfType,
SerializationGraphIsTooBig,
SerializationGraphIsTooDeep,
TypeIsNotValid,
SerializingUnknownType,
SerializingSpecialSystemType,
UnexpectedEndOfStream,
UnexpectedMemberName,
UnexpectedToken,
UnknownEscapeSequence,
UnknownDiscriminatorValue,
SerializationFramesCorruption,
StreamIsNotReadable,
StreamIsNotWriteable,
UnterminatedStringLiteral,
UnknownNotation,
MemberNameIsNotSpecified,
TypeRequiresCustomSerializer
}
public ErrorCode Code { get; set; }
public int LineNumber { get; set; }
public int ColumnNumber { get; set; }
public ulong CharactersWritten { get; set; }
internal JsonSerializationException(string message, ErrorCode errorCode, IJsonReader reader = null)
: base(message)
{
this.Code = errorCode;
if (reader != null)
this.Update(reader);
}
internal JsonSerializationException(string message, ErrorCode errorCode, IJsonReader reader, Exception innerException)
: base(message, innerException)
{
this.Code = errorCode;
if (reader != null)
this.Update(reader);
}
internal JsonSerializationException(string message, Exception innerException)
: base(message, innerException)
{
this.Code = ErrorCode.SerializationException;
}
protected JsonSerializationException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
this.Code = (ErrorCode)info.GetInt32("Code");
this.LineNumber = info.GetInt32("LineNumber");
this.ColumnNumber = info.GetInt32("ColumnNumber");
this.CharactersWritten = info.GetUInt64("CharactersWritten");
}
private void Update(IJsonReader reader)
{
this.LineNumber = reader.Value.LineNumber;
this.ColumnNumber = reader.Value.ColumnNumber;
//this.Path = reader.Value.Path;
}
[SecurityCritical]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Code", (int)this.Code);
info.AddValue("LineNumber", this.LineNumber);
info.AddValue("ColumnNumber", this.ColumnNumber);
info.AddValue("CharactersWritten", this.CharactersWritten);
base.GetObjectData(info, context);
}
public static Exception MemberNameIsEmpty(IJsonReader reader)
{
return new JsonSerializationException
(
string.Format("An empty member name was deserialized. Path: '{0}'", reader.Context.GetPath()),
ErrorCode.EmptyMemberName,
reader
);
}
public static Exception MemberNameIsNotSet()
{
return new JsonSerializationException
(
"A member name is not set before writing value to object.",
ErrorCode.MemberNameIsNotSpecified
);
}
public static Exception DiscriminatorIsNotFirstMember(IJsonReader reader)
{
return new JsonSerializationException
(
string.Format("Discriminator member '{0}' should be first member of object. Path: '{1}'.", ObjectSerializer.TYPE_MEMBER_NAME, reader.Context.GetPath()),
ErrorCode.DiscriminatorNotFirstMemberOfObject,
reader
);
}
public static Exception CantCreateInstanceOfType(Type type)
{
return new JsonSerializationException
(
string.Format("Unable to deserialize instance of '{0}' because ", type.FullName) +
(type.GetTypeInfo().IsAbstract ? "it is an abstract type." : "there is no parameterless constructor is defined on type."),
ErrorCode.CantCreateInstanceOfType
);
}
public static Exception SerializationGraphIsTooBig(IJsonReader reader, ulong maxObjects)
{
return new JsonSerializationException
(
string.Format("Serialization graph is too big. Maximum serialized objects is {0}. Path: '{1}'", maxObjects, reader.Context.GetPath()),
ErrorCode.SerializationGraphIsTooBig
);
}
public static Exception SerializationGraphIsTooDeep(IJsonReader reader, ulong maxDepth)
{
return new JsonSerializationException
(
string.Format("Serialization graph is too deep. Maximum depth is {0}. Path: '{1}'", maxDepth, reader.Context.GetPath()),
ErrorCode.SerializationGraphIsTooDeep)
;
}
public static Exception TypeIsNotValid(Type type, string problem)
{
problem = problem.TrimEnd('.');
return new JsonSerializationException
(
string.Format("Type '{0}' is not valid for serialization: {1}.", type.Name, problem),
ErrorCode.TypeIsNotValid
);
}
public static Exception SerializingUnknownType(Type type)
{
return new JsonSerializationException
(
string.Format("Attempt to serialize unknown type '{0}' failed.", type.FullName),
ErrorCode.SerializingUnknownType
);
}
public static Exception SerializingSpecialSystemType(Type type)
{
return new JsonSerializationException
(
string.Format("Attempt to serialize special system type '{0}' failed. This type is could be serialized.", type.FullName),
ErrorCode.SerializingSpecialSystemType
);
}
public static Exception UnexpectedEndOfStream(IJsonReader reader)
{
return new JsonSerializationException
(
string.Format("Unexpected end of stream while more data is expected. Path: '{0}'.", reader.Context.GetPath()),
ErrorCode.UnexpectedEndOfStream,
reader
);
}
public static Exception UnexpectedMemberName(string memberName, string expected, IJsonReader reader)
{
return new JsonSerializationException
(
string.Format("Unexpected member '{0}' is read while '{1}' is expected. Path: '{2}'.", memberName, expected, reader.Context.GetPath()),
ErrorCode.UnexpectedMemberName,
reader
);
}
public static Exception UnexpectedToken(IJsonReader reader, params JsonToken[] expectedTokens)
{
var tokensStr = default(string);
if (expectedTokens.Length == 0)
{
tokensStr = "<no tokens>";
}
else
{
#if NET40
tokensStr = String.Join(", ", expectedTokens);
#else
var tokens = expectedTokens.ConvertAll(c => c.ToString());
tokensStr = String.Join(", ", tokens);
#endif
}
if (reader.Token == JsonToken.EndOfStream)
{
return UnexpectedEndOfStream(reader);
}
else if (expectedTokens.Length > 1)
{
return new JsonSerializationException
(
string.Format("Unexpected token read '{0}' while any of '{1}' are expected. Path: '{2}'.", reader.Token, tokensStr, reader.Context.GetPath()),
ErrorCode.UnexpectedToken,
reader
);
}
else
{
return new JsonSerializationException
(
string.Format("Unexpected token read '{0}' while '{1}' is expected. Path: '{2}'.", reader.Token, tokensStr, reader.Context.GetPath()),
ErrorCode.UnexpectedToken,
reader
);
}
}
public static Exception UnknownEscapeSequence(string escape, IJsonReader reader)
{
return new JsonSerializationException
(
string.Format("An unknown escape sequence '{0}' is read. Path: '{1}'.", escape, reader.Context.GetPath()),
ErrorCode.UnknownEscapeSequence,
reader
);
}
public static Exception SerializationFramesCorruption()
{
return new JsonSerializationException
(
"Serialization frames are corrupted. Probably invalid Push/Pop sequence in TypeSerializers implementation.",
ErrorCode.SerializationFramesCorruption
);
}
public static Exception StreamIsNotReadable()
{
return new JsonSerializationException
(
"Can\'t perform deserialization from stream which doesn't support reading.",
ErrorCode.StreamIsNotReadable
);
}
public static Exception StreamIsNotWriteable()
{
return new JsonSerializationException
(
"Can\'t perform serialization to stream which doesn't support writing.",
ErrorCode.StreamIsNotWriteable
);
}
public static Exception UnterminatedStringLiteral(IJsonReader reader)
{
return new JsonSerializationException
(
string.Format("An unterminated string literal. Path: '{0}'.", reader.Context.GetPath()),
ErrorCode.UnterminatedStringLiteral,
reader
);
}
public static Exception UnknownNotation(IJsonReader reader, string notation)
{
return new JsonSerializationException
(
string.Format("An unknown notation '{0}'. Path: '{1}'.", notation, reader.Context.GetPath()),
ErrorCode.UnknownNotation,
reader
);
}
public static Exception TypeRequiresCustomSerializer(Type type, Type typeSerializer)
{
return new JsonSerializationException
(
string.Format("Type '{0}' can't be serialized by '{1}' and requires custom {2} registered in 'Json.DefaultSerializers'.", type.FullName, typeSerializer.Name, typeof(TypeSerializer).Name),
ErrorCode.TypeRequiresCustomSerializer
);
}
}
}