using System;
using System.Linq;
using System.Collections.Generic;
using Apolyton.FastJson.Common;
using Apolyton.FastJson.Data;
using Apolyton.FastJson.Registry;
using Apolyton.FastJson.Serialization;
using System.Collections;
namespace Apolyton.FastJson
{
/// <summary>
/// Entry point for json related operations.
/// </summary>
/// <remarks>
/// http://www.codeproject.com/Articles/159450/fastJSON
/// The version over there (2.0.9) could not be taken directly, as its serializer is taking all public properties, disregarding any attribute policy. This is
/// not good for our case, as we want to return (portions of) data objects as well.
/// </remarks>
public sealed class Json
{
[ThreadStatic]
private static Json _current;
private JsonParameters _defaultParameters;
private Json()
{
_defaultParameters = new JsonParameters();
}
/// <summary>
/// Returns the list of members which are concerded by (de-)serialization according to the current default parameters.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public IEnumerable<JsonSerializationInfo> GetSerializationMembers(Type type)
{
return _defaultParameters.GetSerializationMembers(type);
}
/// <summary>
/// Returns a json string for the given object.
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public string ToJson(object obj)
{
_defaultParameters.FixValues();
return ToJson(obj, _defaultParameters);
}
/// <summary>
/// Returns a json string for the given object.
/// </summary>
public string ToJson(object source, JsonParameters param)
{
Guard.ArgumentNotNull(source, "obj");
Guard.ArgumentNotNull(param, "param");
param.FixValues();
Type t = null;
if (source == null)
{
return "null";
}
if (source.GetType().IsGenericType)
{
t = source.GetType().GetGenericTypeDefinition();
}
if (t == typeof(Dictionary<,>) || t == typeof(List<>))
{
param.UsingGlobalTypes = false;
}
// FEATURE : enable extensions when you can deserialize anon types
if (_defaultParameters.EnableAnonymousTypes)
{
param.UseExtensions = false;
param.UsingGlobalTypes = false;
param.SerializationPolicy = SerializationPolicy.PropertyOptOut | SerializationPolicy.IncludeReadOnly;
}
return new JsonSerializer(param).Serialize(source);
}
/// <summary>
/// Builds the instance up with the provided values from the value object. Normally used after ReadJsonValue(String).
/// </summary>
/// <param name="instanceToBuild"></param>
/// <param name="jsonValue"></param>
public void BuildUp(Object instanceToBuild, JsonObject jsonValue)
{
Guard.ArgumentNotNull(instanceToBuild, "instanceToBuild");
if (jsonValue == null) { return; }
new JsonValueDeserializer(_defaultParameters).BuildUp(instanceToBuild, jsonValue);
}
/// <summary>
/// Returns the parsed json string as an object which is IDictionary or IList. Number types are parsed, however all nested objects remain generic implementations
/// of IDictionary or IList.
/// </summary>
/// <param name="jsonString"></param>
/// <returns></returns>
public IEnumerable ReadSomeObject(string jsonString)
{
Guard.ArgumentNotNullOrEmpty(jsonString, "jsonString");
return new JsonHybridDeserializer(_defaultParameters).Deserialize(ref jsonString);
}
/// <summary>
/// Returns the strongly typed object for the given json string.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="jsonString"></param>
/// <returns></returns>
public T ReadObject<T>(string jsonString)
{
Guard.ArgumentNotNullOrEmpty(jsonString, "jsonString");
return (T)ReadObjectInternal(ref jsonString, typeof(T));
}
/// <summary>
/// Returns the object with the best fitting type for the given json string.
/// </summary>
/// <param name="jsonString"></param>
/// <returns></returns>
public object ReadObject(string jsonString)
{
Guard.ArgumentNotNullOrEmpty(jsonString, "jsonString");
return ReadObjectInternal(ref jsonString, null);
}
/// <summary>
/// Returns the object with the specified type for the given json string and the defined target type.
/// </summary>
internal object ReadObject(string jsonString, Type targetType)
{
return ReadObjectInternal(ref jsonString, targetType);
}
/// <summary>
/// Returns the object for the given json string and the defined target type.
/// </summary>
/// <param name="jsonString"></param>
/// <param name="targetType"></param>
/// <returns></returns>
private object ReadObjectInternal(ref string jsonString, Type targetType)
{
Guard.ArgumentNotNullOrEmpty(jsonString, "jsonString");
_defaultParameters.FixValues();
Type t = null;
if (targetType != null && targetType.IsGenericType)
{
t = targetType.GetGenericTypeDefinition();
}
if (t == typeof(Dictionary<,>) || t == typeof(List<>))
{
_defaultParameters.UsingGlobalTypes = false;
}
return new JsonObjectDeserializer(_defaultParameters).Deserialize(ref jsonString, targetType);
}
/// <summary>
/// Returns the json value object for the given json string.
/// </summary>
/// <param name="jsonString"></param>
/// <returns></returns>
public IJsonValue ReadJsonValue(string jsonString)
{
Guard.ArgumentNotNullOrEmpty(jsonString, "jsonString");
return new JsonValueDeserializer(_defaultParameters).Deserialize(ref jsonString);
}
/// <summary>
/// Builds up the instance based on the given json object values.
/// </summary>
/// <param name="instanceToBuild">A non-null instance which is populated with the provided values</param>
/// <param name="values">The values which should fill the given instance.</param>
/// <param name="throwOnMissingValue">If true, it throws an exception when a specified (by the instance) value is not present in the json object.</param>
/// <exception cref="ArgumentNullException"/>
internal void BuildUp(Object instanceToBuild, JsonObject values, bool throwOnMissingValue)
{
Guard.ArgumentNotNull(instanceToBuild, "instanceToBuild");
Guard.ArgumentNotNull(values, "values");
new JsonValueDeserializer(_defaultParameters).BuildUp(instanceToBuild, values);
}
/// <summary>
/// Returns a beautified string of the given json string.
/// </summary>
/// <param name="jsonString"></param>
/// <returns></returns>
public string Beautify(string jsonString)
{
Guard.ArgumentNotNull(jsonString, "jsonString");
if (jsonString == String.Empty) { return String.Empty; }
return Formatter.PrettyPrint(jsonString);
}
/// <summary>
/// Creates a clone of the object by serialize and deserialize it again.
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public object DeepCopy(object source)
{
Guard.ArgumentNotNull(source, "source");
return ReadObject(ToJson(source));
}
/// <summary>
/// Creates a clone of the object by serialize and deserialize it again.
/// </summary>
public T DeepCopy<T>(T source)
{
Guard.ArgumentNotNull(source, "source");
return ReadObject<T>(ToJson(source));
}
/// <summary>
/// Registers a custom type.
/// </summary>
/// <param name="type"></param>
/// <param name="serializer"></param>
/// <param name="deserializer"></param>
public void RegisterCustomType(Type type, SerializationHandler serializer, DeserializationHandler deserializer)
{
Guard.ArgumentNotNull(serializer, "type");
Guard.ArgumentNotNull(serializer, "serializer");
Guard.ArgumentNotNull(deserializer, "deserializer");
_defaultParameters.Registry.RegisterCustomType(type, serializer, deserializer);
}
/// <summary>
/// Gets the json instance.
/// </summary>
public static Json Current
{
get { return _current ?? (_current = new Json()); }
}
/// <summary>
/// Gets or sets the default parameters.
/// </summary>
public JsonParameters DefaultParameters
{
get { return _defaultParameters; }
set { _defaultParameters = value; }
}
}
}