Может ли Json.NET сериализовать / десериализовать в / из streamа?

Я слышал, что Json.NET быстрее, чем DataContractJsonSerializer, и хотел дать ему попробовать …

Но я не мог найти никаких методов в JsonConvert, которые берут stream, а не строку.

Например, для десериализации файла, содержащего JSON на WinPhone, я использую следующий код, чтобы прочитать содержимое файла в строке, а затем десериализоваться в JSON. В моем (очень ad-hoc) тестировании он примерно в 4 раза медленнее, чем с использованием DataContractJsonSerializer для десериализации прямо из streamа …

// DCJS DataContractJsonSerializer dc = new DataContractJsonSerializer(typeof(Constants)); Constants constants = (Constants)dc.ReadObject(stream); // JSON.NET string json = new StreamReader(stream).ReadToEnd(); Constants constants = JsonConvert.DeserializeObject(json); 

Я делаю это неправильно?

Благодаря,

Омри.

UPDATE: это больше не работает в текущей версии, см. Ниже правильный ответ ( нет необходимости проголосовать, это верно в старых версиях ).

Используйте class JsonTextReader с StreamReader или используйте перегрузку JsonSerializer , StreamReader напрямую использует StreamReader :

 var serializer = new JsonSerializer(); serializer.Deserialize(streamReader); 

Текущая версия Json.net не позволяет использовать принятый код ответа. Текущая альтернатива:

 public static object DeserializeFromStream(Stream stream) { var serializer = new JsonSerializer(); using (var sr = new StreamReader(stream)) using (var jsonTextReader = new JsonTextReader(sr)) { return serializer.Deserialize(jsonTextReader); } } 

Документация: десериализация JSON из файлового streamа

 public static void Serialize(object value, Stream s) { using (StreamWriter writer = new StreamWriter(s)) using (JsonTextWriter jsonWriter = new JsonTextWriter(writer)) { JsonSerializer ser = new JsonSerializer(); ser.Serialize(jsonWriter, value); jsonWriter.Flush(); } } public static T Deserialize(Stream s) { using (StreamReader reader = new StreamReader(s)) using (JsonTextReader jsonReader = new JsonTextReader(reader)) { JsonSerializer ser = new JsonSerializer(); return ser.Deserialize(jsonReader); } } 

Я написал class расширения, чтобы помочь мне десериализоваться из источников JSON (строка, stream, файл).

 public static class JsonHelpers { public static T CreateFromJsonStream(this Stream stream) { JsonSerializer serializer = new JsonSerializer(); T data; using (StreamReader streamReader = new StreamReader(stream)) { data = (T)serializer.Deserialize(streamReader, typeof(T)); } return data; } public static T CreateFromJsonString(this String json) { T data; using (MemoryStream stream = new MemoryStream(System.Text.Encoding.Default.GetBytes(json))) { data = CreateFromJsonStream(stream); } return data; } public static T CreateFromJsonFile(this String fileName) { T data; using (FileStream fileStream = new FileStream(fileName, FileMode.Open)) { data = CreateFromJsonStream(fileStream); } return data; } } 

Deserializing теперь так же просто, как писать:

 MyType obj1 = aStream.CreateFromJsonStream(); MyType obj2 = "{\"key\":\"value\"}".CreateFromJsonString(); MyType obj3 = "data.json".CreateFromJsonFile(); 

Надеюсь, это поможет кому-то другому.

Я пришел к этому вопросу, ища способ streamового streamа объектов с открытым System.IO.Stream в System.IO.Stream и считывать их с другого конца без буферизации всего списка перед отправкой. (В частности, я передаю сохраненные объекты из MongoDB через веб-интерфейс API.)

@Paul Tyng и @Rivers сделали отличную работу, отвечая на исходный вопрос, и я использовал их ответы, чтобы построить доказательство концепции для моей проблемы. Я решил разместить здесь тестовое консольное приложение, если кто-то другой столкнулся с той же проблемой.

 using System; using System.Diagnostics; using System.IO; using System.IO.Pipes; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; namespace TestJsonStream { class Program { static void Main(string[] args) { using(var writeStream = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.None)) { string pipeHandle = writeStream.GetClientHandleAsString(); var writeTask = Task.Run(() => { using(var sw = new StreamWriter(writeStream)) using(var writer = new JsonTextWriter(sw)) { var ser = new JsonSerializer(); writer.WriteStartArray(); for(int i = 0; i < 25; i++) { ser.Serialize(writer, new DataItem { Item = i }); writer.Flush(); Thread.Sleep(500); } writer.WriteEnd(); writer.Flush(); } }); var readTask = Task.Run(() => { var sw = new Stopwatch(); sw.Start(); using(var readStream = new AnonymousPipeClientStream(pipeHandle)) using(var sr = new StreamReader(readStream)) using(var reader = new JsonTextReader(sr)) { var ser = new JsonSerializer(); if(!reader.Read() || reader.TokenType != JsonToken.StartArray) { throw new Exception("Expected start of array"); } while(reader.Read()) { if(reader.TokenType == JsonToken.EndArray) break; var item = ser.Deserialize(reader); Console.WriteLine("[{0}] Received item: {1}", sw.Elapsed, item); } } }); Task.WaitAll(writeTask, readTask); writeStream.DisposeLocalCopyOfClientHandle(); } } class DataItem { public int Item { get; set; } public override string ToString() { return string.Format("{{ Item = {0} }}", Item); } } } } 

Обратите внимание, что вы можете получить исключение, когда AnonymousPipeServerStream находится, я проигнорировал это, поскольку он не имеет отношения к проблеме.

  • Заставить JSON.NET включать миллисекунды при сериализации DateTime (даже если компонент ms равен нулю)
  • Deserialize специфическое перечисление в system.enum в Json.Net
  • jackson не десериализует общий список, который он сериализовал
  • Использование JsonConvert.DeserializeObject для десериализации Json в class C # POCO
  • Json Сериализация Java, которая работает с GWT
  • Как использовать пользовательский Serializer с Jackson?
  • Java: объект для байта и байт для конвертера объектов (для Tokyo Cabinet)
  • Когда и почему сущности JPA должны реализовывать интерфейс Serializable?
  • C # JSON.NET - десериализация ответа, использующего необычную структуру данных
  • jQuery serializeArray не включает кнопку отправки, которая была нажата
  • Использование преобразователей Json.NET для десериализации свойств
  • Давайте будем гением компьютера.