জসন.এনইটি কোনও স্ট্রিমের / থেকে সিরিয়ালাইজ / ডিসরিয়ালাইজ করতে পারে?


151

আমি শুনেছি যে Json.NET ডেটা কন্ট্রাক্ট জসনসিরাইজারের চেয়ে দ্রুত এবং এটি চেষ্টা করে দেখতে চেয়েছিল ...

তবে আমি জসনকনভার্টে এমন কোনও পদ্ধতি খুঁজে পাইনি যা স্ট্রিংয়ের পরিবর্তে স্ট্রিম গ্রহণ করে।

উইনফোনে জেএসএন সমন্বিত একটি ফাইলকে ডেসিরিয়ালাইজ করার জন্য, উদাহরণস্বরূপ, আমি ফাইলের বিষয়বস্তুগুলিকে স্ট্রিংয়ে পড়তে নীচের কোডটি ব্যবহার করি এবং তারপরে জেএসএন-তে deserialize করি। আমার (খুব অ্যাডহক) পরীক্ষায় এটি স্ট্রিম থেকে সরাসরি ডিসস্রায়ালাইজ করার জন্য ডেটা কন্ট্র্যাক্ট জসনসিরাইজার ব্যবহার করার চেয়ে প্রায় 4 গুণ ধীর বলে মনে হচ্ছে ...

// 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<Constants>(json);

আমি কি এটা ভুল করছি?

উত্তর:


58

আপডেট: এটি আর বর্তমান সংস্করণে কাজ করে না, সঠিক উত্তরের জন্য নীচে দেখুন ( ভোট দেওয়ার দরকার নেই, পুরানো সংস্করণগুলিতে এটি সঠিক )।

ব্যবহার করুন JsonTextReaderএকটি সঙ্গে বর্গ StreamReaderবা ব্যবহার JsonSerializerজমিদার করে একটি লাগে StreamReaderসরাসরি:

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

23
খুব নিশ্চিত যে এটি আর কাজ করে না। আপনাকে একটি জসনরেডার বা টেক্সটরিডার ব্যবহার করতে হবে
ব্র্যাডলনে

8
আপনি এখনও যে সংস্করণ নম্বরটি কাজ করছেন তা অন্তর্ভুক্ত করতে চাইতে পারেন যাতে লোকে কখন জানতে পারে যে কখন নীচে নামবে।
পোঃএইচএইচ

ব্র্যাডলনেই ইউএসপ জসনটেক্সটআরডার (প্রদত্ত স্ট্রিমরিডার) এখন যাবার উপায়
এন্টোইন মেল্টজহিম

আপনার উত্তরটি কার্য সম্পাদন করতে ও পুনরায় সুপারিশ করার জন্য সময় দেওয়ার জন্য ধন্যবাদ
নিক বুল

281

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);
    }
}

ডকুমেন্টেশন: একটি ফাইল স্ট্রিম থেকে জেএসওনকে ডিসিজরিয়াল করুন


4
জসনটেক্সটআরডার তার স্ট্রিমরিডার ডিফল্টরূপে বন্ধ করে দেবে, সুতরাং এই উদাহরণটি জসনটেক্সটরিডার কনস্ট্রাক্টরের কাছে কল করে স্ট্রিমরিডার তৈরি করে কিছুটা সহজ করা যায়।
অলিভার বক

1
এই কোড সহ আমি কীভাবে একটি কাস্টম রূপান্তরকারী ব্যবহার করতে পারি তার কোনও ধারণা? সিরিয়ালাইজারটি ব্যবহার করার জন্য কোনও রূপান্তরকারী নির্দিষ্ট করার কোনও উপায় দেখুন না
সর্বদা

1
প্রকৃতপক্ষে, আমার কাছে একটি আউটআমমোরি ব্যতিক্রম আছে এবং আমি ইতিমধ্যে এই কোডটি ব্যবহার করেছি, বেশ খানিকটা ঠিক। কোনটি, আমি বিশ্বাস করি, এটি গ্যারান্টি নয় - যদি ডিসরিয়ালাইজড অবজেক্টটি যথেষ্ট পরিমাণে বড় হয় এবং আপনি 32-বিট প্রক্রিয়ায় আটকে থাকেন তবে আপনি এই
কোডটির

1
আমি একটি ত্রুটি পাচ্ছি "টাইপ বা নেমস্পেসের নাম 'JsonTextReader' পাওয়া যায়নি" ... কোনও পরামর্শ?
hnvasa

1
আমার stream.Position = 0;জসনকে সঠিকভাবে ডিসরিয়ালাইজ করার জন্য আমাকে যুক্ত করা দরকার ।
হাইব্রিড 2102

76
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<T>(Stream s)
{
    using (StreamReader reader = new StreamReader(s))
    using (JsonTextReader jsonReader = new JsonTextReader(reader))
    {
        JsonSerializer ser = new JsonSerializer();
        return ser.Deserialize<T>(jsonReader);
    }
}

2
ধন্যবাদ! আমি যখন স্ট্রিংয়ে খুব বড় একটি অবজেক্ট কালেকশন সিরিয়ালাইজ করছিলাম এবং তারপরে সেই স্ট্রিংটি আমার স্ট্রিমে লিখেছিলাম (কেবল প্রবাহে সরাসরি সিরিয়ালাইজ করার পরিবর্তে) এটি আউটআউট-মেমরিএক্সেপশন এড়াতে আমাকে সহায়তা করেছিল।
জন স্নাইডার

2
ফ্লাশ কেন? ব্যবহারের ব্লকটির কারণে নিষ্পত্তি কল কি ইতিমধ্যে তা করে না?
akafak Gür

এটি কিভাবে ব্যবহার করতে ?
সানা 10

2
সাইড নোট, কারণ এটি অন্যকে সহায়তা করতে পারে: আপনি যদি ব্যবহার করেন তবে আপনি JsonSerializer ser = JsonSerializer.Create(settings);ডি / সিরিয়ালাইজেশনের সময় কোন সেটিংস ব্যবহার করবেন তা নির্ধারণ করতে পারেন।
মাইক

1
এই Serializeপ্রয়োগের সাথে একটি সম্ভাব্য সমস্যা হ'ল এটি Streamআর্গুমেন্ট হিসাবে পাসটি বন্ধ করে দেয় , যা প্রয়োগের উপর নির্ভর করে সমস্যা হতে পারে। .NET 4.5+ এর সাহায্যে আপনি StreamWriterপ্যারামিটার দিয়ে কনস্ট্রাক্টর ওভারলোড ব্যবহার করে এই সমস্যাটি এড়াতে পারবেন যা leaveOpenআপনাকে স্ট্রিমটি উন্মুক্ত রাখতে দেয়।
জো

29

আমি JSON উত্স (স্ট্রিং, স্ট্রিম, ফাইল) থেকে ডিসিরিয়ালাইজিংয়ে সহায়তা করতে একটি এক্সটেনশন ক্লাস লিখেছি।

public static class JsonHelpers
{
    public static T CreateFromJsonStream<T>(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<T>(this String json)
    {
        T data;
        using (MemoryStream stream = new MemoryStream(System.Text.Encoding.Default.GetBytes(json)))
        {
            data = CreateFromJsonStream<T>(stream);
        }
        return data;
    }

    public static T CreateFromJsonFile<T>(this String fileName)
    {
        T data;
        using (FileStream fileStream = new FileStream(fileName, FileMode.Open))
        {
            data = CreateFromJsonStream<T>(fileStream);
        }
        return data;
    }
}

ডিসরিয়ালাইজ করা এখন লেখার মতোই সহজ:

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

আশা করি এটি অন্য কাউকে সাহায্য করবে।


2
এর বিপরীতে : এটি এক্সটেনশন পদ্ধতির সাথে সমস্ত স্ট্রিংকে দূষিত করবে। কর্মক্ষেত্র : কেবল Using SomeJsonHelpersNamespaceকোথায় প্রয়োজন তা ঘোষণা করুন বা thisকীওয়ার্ডটি সরিয়ে দিন এবং JsonHelpers.CreateFromJsonString(someJsonString) প্রো ব্যবহার করুন : এটি ব্যবহার করা এত সহজ :)
টোক '

1
যদিও এটি "দূষণকারী" হিসাবে দেখা যেতে পারে, স্ট্রিং অবজেক্টে প্রায় অর্ধেক এক্সটেনশন একইভাবে দেখা যেতে পারে। এটি এমনভাবে কোনও অবজেক্টকে প্রসারিত করে যেটিকে কারওরূপে কার্যকর হিসাবে দেখা যায় যা ধারাবাহিকভাবে স্ট্রিং (জেসন) থেকে জেএসএনে পরিবর্তিত হয়।
ভাইপারসাসসিন

Encoding.Defaultএটি ব্যবহার করাও খারাপ কারণ এটি বিভিন্ন মেশিনে আলাদা আচরণ করবে (মাইক্রোসফ্ট ডকুমেন্টে বড় সতর্কতা দেখুন)। জেএসওএন ইউটিএফ -8 হবে বলে আশা করা হচ্ছে এবং এটি জাসনসিরাইজার আশা করে। সুতরাং এটি হওয়া উচিত Encoding.UTF8। হিসাবে কোডটি গাবল্ড স্ট্রিং উত্পাদন করে বা অ-এসসিআইআই অক্ষর ব্যবহার না করা হলে ডিসিরিয়ালাইজ করতে ব্যর্থ হবে।
ckuri

17

আমি এই প্রশ্নে পৌঁছেছি একটি ওপেনের অবজেক্টের তালিকাটি স্ট্রিম করার জন্য System.IO.Streamএবং অন্য প্রান্তে পাঠানোর আগে পুরো তালিকায় বাফারিং ছাড়াই সেগুলি পড়তে চাই looking (বিশেষত আমি মঙ্গোডিবি থেকে ওয়েব এপিআইয়ের মাধ্যমে স্থির অবজেক্টগুলি স্ট্রিম করছি)

@ পোল টাইং এবং @ রিভার্স মূল প্রশ্নের উত্তর দেওয়ার জন্য দুর্দান্ত কাজ করেছিলেন এবং আমি তাদের উত্তরগুলি আমার সমস্যার জন্য ধারণার প্রমাণ তৈরি করতে ব্যবহার করেছি। অন্য কেউ যদি একই সমস্যার মুখোমুখি হয় তবে আমি এখানে আমার পরীক্ষার কনসোল অ্যাপটি পোস্ট করার সিদ্ধান্ত নিয়েছি।

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<DataItem>(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নিষ্পত্তি করার সময় আপনি একটি ব্যতিক্রম পেতে পারেন, এটি এহেন সমস্যার সাথে প্রাসঙ্গিক না বলে আমি এটিকে উপেক্ষা করেছি।


1
আমার এটিকে সংশোধন করতে হবে যাতে আমি কোনও সম্পূর্ণ JSON অবজেক্ট পেতে পারি। আমার সার্ভার এবং ক্লায়েন্ট JSON এর স্নিপেট পাঠিয়ে যোগাযোগ করে যাতে ক্লায়েন্টটি প্রেরণ করতে পারে {"sign in":{"username":"nick"}}{"buy item":{"_id":"32321123"}}এবং প্রতিটি বার এটি একটি খণ্ড পড়ার সময় একটি ইভেন্টের সিগন্যাল করে এটি JSON এর দুটি টুকরো হিসাবে এটি দেখতে হবে। নোডেজে এটি কোডের 3 লাইনে করা যায়।
নিক সোটিরিস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.