Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process streamed data #174

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions Jil/Deserialize/InlineDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -899,16 +899,19 @@ void ExpectEndOfStream()
Emit.LoadArgument(1); // int
Emit.LoadConstant(0); // int
Emit.UnsignedBranchIfNotEqual(success); // --empty --
ReadCharFromStream(); // int
Emit.LoadConstant(-1); // int -1
Emit.BranchIfEqual(success); // --empty--

Emit.LoadConstant("Expected end of stream"); // string
Emit.LoadArgument(0); // string TextReader
Emit.LoadConstant(false); // string TextReader bool
ThrowStringStreamBool(); // DeserializationException
Emit.Throw(); // --empty--

if (!OptionsType.IsGenericType || OptionsType.GetGenericTypeDefinition() != typeof(StreamedOption<>))
{
ReadCharFromStream(); // int
Emit.LoadConstant(-1); // int -1
Emit.BranchIfEqual(success); // --empty--

Emit.LoadConstant("Expected end of stream"); // string
Emit.LoadArgument(0); // string TextReader
Emit.LoadConstant(false); // string TextReader bool
ThrowStringStreamBool(); // DeserializationException
Emit.Throw(); // --empty--
}
Emit.MarkLabel(success); // --empty--
}

Expand Down
21 changes: 21 additions & 0 deletions Jil/Deserialize/TypeCaches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,25 @@ class RFC1123StyleCamelCase : IDeserializeOptions
public DateTimeFormat DateFormat { get { return DateTimeFormat.RFC1123; } }
public SerializationNameFormat SerializationNameFormat { get { return SerializationNameFormat.CamelCase; } }
}


class StreamedOption<TOptions> : IDeserializeOptions where TOptions : class, IDeserializeOptions, new()
{
private TOptions wrapped;

private TOptions Wrapped
{
get { return wrapped ?? (wrapped = new TOptions()); }
}

public DateTimeFormat DateFormat
{
get { return Wrapped.DateFormat; }
}

public SerializationNameFormat SerializationNameFormat
{
get { return Wrapped.SerializationNameFormat; }
}
}
}
120 changes: 119 additions & 1 deletion Jil/JSON.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4653,6 +4653,124 @@ public static object Deserialize(string text, Type type, Options options = null)
}

return Jil.Deserialize.DeserializeIndirect.DeserializeFromString(text, type, options);
}

/// <summary>
/// Deserializes multiple JSON objects from the given TextReader.
///
/// Pass an Options object to specify the particulars (such as DateTime formats) of
/// the JSON being deserialized. If omitted Options.Default is used, unless JSON.SetDefaultOptions(Options) has been
/// called with a different Options object.
/// </summary>
/// <remarks>
/// This method can be used to deserialize and iterate objects while new data is still written to the stream.
/// The JSON objects contained in the stream must not be separated by any delimiter (whitespaces are ignored).
/// </remarks>
public static IEnumerable<T> DeserializeStream<T>(TextReader reader, Options options = null)
{
if (reader == null)
{
throw new ArgumentNullException("reader");
}

if (typeof(T) == typeof(object))
{
throw new NotSupportedException("Dynamic/Object data types are currently not supported.");
}

Func<TextReader, int, T> deserializer = null;

try
{
options = options ?? DefaultOptions;
reader = reader.MakeSupportPeek();


switch (options.UseDateTimeFormat)
{
case DateTimeFormat.MicrosoftStyleMillisecondsSinceUnixEpoch:
switch (options.SerializationNameFormat)
{
case SerializationNameFormat.Verbatim:
deserializer = Jil.Deserialize.TypeCache<Jil.Deserialize.StreamedOption<Jil.Deserialize.MicrosoftStyle>, T>.Get();
break;
case SerializationNameFormat.CamelCase:
deserializer = Jil.Deserialize.TypeCache<Jil.Deserialize.StreamedOption<Jil.Deserialize.MicrosoftStyleCamelCase>, T>.Get();
break;
}
break;
case DateTimeFormat.MillisecondsSinceUnixEpoch:
switch (options.SerializationNameFormat)
{
case SerializationNameFormat.Verbatim:
deserializer = Jil.Deserialize.TypeCache<Jil.Deserialize.StreamedOption<Jil.Deserialize.MillisecondStyle>, T>.Get();
break;
case SerializationNameFormat.CamelCase:
deserializer = Jil.Deserialize.TypeCache<Jil.Deserialize.StreamedOption<Jil.Deserialize.MillisecondStyleCamelCase>, T>.Get();
break;
}
break;
case DateTimeFormat.SecondsSinceUnixEpoch:
switch (options.SerializationNameFormat)
{
case SerializationNameFormat.Verbatim:
deserializer = Jil.Deserialize.TypeCache<Jil.Deserialize.StreamedOption<Jil.Deserialize.SecondStyle>, T>.Get();
break;
case SerializationNameFormat.CamelCase:
deserializer = Jil.Deserialize.TypeCache<Jil.Deserialize.StreamedOption<Jil.Deserialize.SecondStyleCamelCase>, T>.Get();
break;
}
break;
case DateTimeFormat.ISO8601:
switch (options.SerializationNameFormat)
{
case SerializationNameFormat.Verbatim:
deserializer = Jil.Deserialize.TypeCache<Jil.Deserialize.StreamedOption<Jil.Deserialize.ISO8601Style>, T>.Get();
break;
case SerializationNameFormat.CamelCase:
deserializer = Jil.Deserialize.TypeCache<Jil.Deserialize.StreamedOption<Jil.Deserialize.ISO8601StyleCamelCase>, T>.Get();
break;
}
break;
case DateTimeFormat.RFC1123:
switch (options.SerializationNameFormat)
{
case SerializationNameFormat.Verbatim:
deserializer = Jil.Deserialize.TypeCache<Jil.Deserialize.StreamedOption<Jil.Deserialize.RFC1123Style>, T>.Get();
break;
case SerializationNameFormat.CamelCase:
deserializer = Jil.Deserialize.TypeCache<Jil.Deserialize.StreamedOption<Jil.Deserialize.RFC1123StyleCamelCase>, T>.Get();
break;
}
break;
default:
throw new InvalidOperationException("Unexpected Options: " + options);
}
}
catch (Exception e)
{
if (e is DeserializationException) throw;

throw new DeserializationException(e, reader, false);
}

if (deserializer == null) throw new DeserializationException("No deserializer available.", reader, false);

while (reader.Peek() != -1)
{
T item;
try
{
item = deserializer(reader, 0);
}
catch (Exception e)
{
if (e is DeserializationException) throw;

throw new DeserializationException(e, reader, false);
}
yield return item;
}
}

/// <summary>
Expand Down Expand Up @@ -4818,7 +4936,7 @@ public static T Deserialize<T>(string text, Options options = null)

throw new DeserializationException(e, false);
}
}
}

/// <summary>
/// Deserializes JSON from the given TextReader, inferring types from the structure of the JSON text.
Expand Down
Loading