JSON.stringify ব্যবহার করে কোনও ত্রুটি তৈরি করা সম্ভব নয়?


330

সমস্যা পুনরুত্পাদন

ওয়েব সকেট ব্যবহার করে চারপাশে ত্রুটি বার্তাগুলি পাস করার চেষ্টা করার সময় আমি একটি সমস্যার মধ্যে চলে আসছি। আমি JSON.stringifyবিস্তৃত শ্রোতাদের পরিবেশন করতে যে সমস্যার মুখোমুখি হয়েছি তার প্রতিলিপি করতে পারি :

// node v0.10.15
> var error = new Error('simple error message');
    undefined

> error
    [Error: simple error message]

> Object.getOwnPropertyNames(error);
    [ 'stack', 'arguments', 'type', 'message' ]

> JSON.stringify(error);
    '{}'

সমস্যাটি হ'ল আমি একটি খালি জিনিস দিয়ে শেষ করি।

আমি কি চেষ্টা করেছি

ব্রাউজার

আমি প্রথমে নোড.জেগুলি রেখে বিভিন্ন ব্রাউজারে এটি চালানোর চেষ্টা করেছি। ক্রোম সংস্করণ ২৮ আমাকে একই ফলাফল দেয় এবং আকর্ষণীয়ভাবে যথেষ্ট, ফায়ারফক্স অন্তত চেষ্টা করে তবে বার্তাটি বাদ দেয়:

>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1\n"}

Replacer ফাংশন

আমি তখন ত্রুটি.প্রোটোটাইপটি তাকালাম । এটা দেখায় যে প্রোটোটাইপ যেমন পদ্ধতি রয়েছে toString এবং toSource । ফাংশনগুলি স্ট্রাইটিং করা যায় না তা জেনে আমি JSON.stringify কে ফোন করে সমস্ত ফাংশন সরিয়ে ফেলতে পেরে একটি প্রতিস্থাপনকারী ফাংশন অন্তর্ভুক্ত করেছি , কিন্তু তখন বুঝতে পেরেছিলাম যে এটিরও কিছু অদ্ভুত আচরণ ছিল:

var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
    console.log(key === ''); // true (?)
    console.log(value === error); // true (?)
});

এটি সাধারণভাবে যেমনটি হবে ঠিক তেমন লুপটি মনে হচ্ছে না এবং অতএব আমি কীটি কোনও ফাংশন কিনা তা পরীক্ষা করতে পারি এবং এটিকে উপেক্ষা করতে পারি না।

প্রশ্নটি

দেশীয় ত্রুটি বার্তাগুলির সাথে JSON.stringifyকীভাবে কোনও উপায় আছে ? যদি তা না হয় তবে কেন এই আচরণ ঘটে?

এই কাছাকাছি পেতে পদ্ধতি

  • সাধারণ স্ট্রিং-ভিত্তিক ত্রুটি বার্তাগুলির সাথে আটকে থাকুন বা ব্যক্তিগত ত্রুটিযুক্ত বস্তু তৈরি করুন এবং নেটিভ ত্রুটিযুক্ত বস্তুর উপর নির্ভর করবেন না।
  • বৈশিষ্ট্য টানুন: JSON.stringify({ message: error.message, stack: error.stack })

আপডেট

@ রায় তোয়াল একটি মন্তব্যে প্রস্তাবিত যে আমি সম্পত্তি বর্ণনাকারীদের দিকে নজর রাখি । এটি কেন কাজ করে না তা এখন স্পষ্ট:

var error = new Error('simple error message');
var propertyNames = Object.getOwnPropertyNames(error);
var descriptor;
for (var property, i = 0, len = propertyNames.length; i < len; ++i) {
    property = propertyNames[i];
    descriptor = Object.getOwnPropertyDescriptor(error, property);
    console.log(property, descriptor);
}

আউটপুট:

stack { get: [Function],
  set: [Function],
  enumerable: false,
  configurable: true }
arguments { value: undefined,
  writable: true,
  enumerable: false,
  configurable: true }
type { value: undefined,
  writable: true,
  enumerable: false,
  configurable: true }
message { value: 'simple error message',
  writable: true,
  enumerable: false,
  configurable: true }

কী: enumerable: false

স্বীকৃত উত্তর এই সমস্যার জন্য একত্রে কাজ করে।


3
আপনি কি ত্রুটিযুক্ত বস্তুর বৈশিষ্ট্যগুলির জন্য সম্পত্তি বর্ণনাকারী পরীক্ষা করেছেন?
রায় তোয়াল

3
আমার জন্য প্রশ্নটি 'কেন' ছিল এবং আমি খুঁজে পেয়েছি উত্তরটি প্রশ্নের নীচে ছিল। আপনার নিজের প্রশ্নের উত্তর পোস্ট করার ক্ষেত্রে কোনও অসুবিধা নেই, এবং সম্ভবত আপনি আরও ক্রেডিট পাবেন। :-)
মাইকেল শ্যাপার 5

উত্তর:


178

প্রতিনিধিত্ব করে এমন Error.prototype.toJSONএকটি সমতল পুনরুদ্ধার করতে আপনি একটি সংজ্ঞা দিতে পারেন :ObjectError

if (!('toJSON' in Error.prototype))
Object.defineProperty(Error.prototype, 'toJSON', {
    value: function () {
        var alt = {};

        Object.getOwnPropertyNames(this).forEach(function (key) {
            alt[key] = this[key];
        }, this);

        return alt;
    },
    configurable: true,
    writable: true
});
var error = new Error('testing');
error.detail = 'foo bar';

console.log(JSON.stringify(error));
// {"message":"testing","detail":"foo bar"}

ব্যবহার Object.defineProperty()যোগ করা toJSONএটি একটি ছাড়া enumerableসম্পত্তি নিজেই।


পরিবর্তনের বিষয়ে Error.prototype, যদিও এর toJSON()জন্য Errorনির্দিষ্টভাবে সংজ্ঞায়িত করা যায় না , তবুও পদ্ধতিটি সাধারণভাবে অবজেক্টগুলির জন্য মানক করা হয় (রেফ: ধাপ 3)। সুতরাং, সংঘর্ষ বা দ্বন্দ্বের ঝুঁকি ন্যূনতম।

যদিও এটি এখনও পুরোপুরি এড়াতে, JSON.stringify()এর replacerপ্যারামিটার পরিবর্তে ব্যবহার করা যেতে পারে:

function replaceErrors(key, value) {
    if (value instanceof Error) {
        var error = {};

        Object.getOwnPropertyNames(value).forEach(function (key) {
            error[key] = value[key];
        });

        return error;
    }

    return value;
}

var error = new Error('testing');
error.detail = 'foo bar';

console.log(JSON.stringify(error, replaceErrors));

3
আপনি যদি এর .getOwnPropertyNames()পরিবর্তে ব্যবহার করেন তবে আপনি অগণিত .keys()বৈশিষ্ট্যগুলি ম্যানুয়ালি সংজ্ঞায়িত না করে পেয়ে যাবেন।

8
ত্রুটি.প্রোটোটাইপে যুক্ত না হওয়া ভাল, জাভাস্ক্রিপ্টের ভবিষ্যতের সংস্করণে ত্রুটি.প্রোটোটাইপ আসলে একটি টোএসএন ফাংশন রাখলে সমস্যাগুলি দিতে পারে।
জোস ডি জং

3
সাবধান হন! এই সমাধানটি দেশীয় নোড মোংডোডব ড্রাইভারগুলিতে ত্রুটি পরিচালনার জন্য বিরতি দেয়: jira.mongodb.org/browse/NODE-554
সেবাস্তিয়ান নওক

5
যদি কেউ তাদের linker ত্রুটি এবং নামকরণ দ্বন্দ্ব মনোযোগ বহন করেনা: replacer বিকল্প ব্যবহার করে যদি, আপনি কি অন্য কিছু প্যারামিটার নাম নির্বাচন করা উচিত জন্য keyfunction replaceErrors(key, value)সঙ্গে সংঘাতে নামকরণ এড়াতে .forEach(function (key) { .. }); এই replaceErrors keyউত্তরটিতে প্যারামিটারটি অব্যবহৃত।
404

2
keyএই উদাহরণটির ছায়া গোছানো , অনুমোদিত হওয়ার পরেও এটি সম্ভাব্য বিভ্রান্তিকর কারণ এতে লেখক বাইরের ভেরিয়েবলটি উল্লেখ করবেন কিনা তা সন্দেহ পোষণ করে। propNameঅভ্যন্তরীণ লুপের জন্য আরও ভাবপূর্ণ পছন্দ হবে choice (বিটিডাব্লু, আমি মনে করি @ ৪০৪ নটফাউন্ডের অর্থ "লিন্টার" (স্ট্যাটিক বিশ্লেষণ সরঞ্জাম) "লিঙ্কার" নয় ) কোনও ক্ষেত্রেই কাস্টম replacerফাংশন ব্যবহার করা এটির জন্য একটি দুর্দান্ত সমাধান কারণ এটি সমস্যাটিকে এক, উপযুক্ত জায়গায় সমাধান করে এবং দেশীয় পরিবর্তন করে না / গ্লোবাল আচরণ।
আইএক্স 3

261
JSON.stringify(err, Object.getOwnPropertyNames(err))

কাজ মনে হচ্ছে

[ / ইউ / ub3rgeek দ্বারা / আর / জাভাস্ক্রিপ্টের একটি মন্তব্য থেকে ] এবং নীচে ফেলিক্সফেকেকারের মন্তব্য


57
উত্তরগুলি JSON.stringify(err, Object.getOwnPropertyNames(err))
কম্বিং করা হচ্ছে

5
এটি একটি নেটিভ এক্সপ্রেসজেএস ত্রুটি অবজেক্টের জন্য দুর্দান্ত কাজ করে তবে এটি মঙ্গুজ ত্রুটির সাথে কাজ করবে না। মঙ্গুজ ত্রুটিগুলি ValidationErrorধরণের জন্য নেস্টেড অবজেক্টস রয়েছে । এটি মংগুজ ত্রুটিযুক্ত errorsধরণের বস্তুতে নেস্টেড অবজেক্টটিকে শক্তিশালী করবে না ValidationError
২৪:৪৯-

4
এটি উত্তর হওয়া উচিত, কারণ এটি করার সহজ উপায় it's
হুয়ান

7
@ ফেলিক্স্ফবেকার এটি কেবলমাত্র এক স্তরের গভীরতার জন্য সম্পত্তিগুলির নাম সন্ধান করে । আপনার যদি আছে var spam = { a: 1, b: { b: 2, b2: 3} };এবং চালনা করে তবে Object.getOwnPropertyNames(spam)আপনি পাবেন ["a", "b"]- এখানে প্রতারণাপূর্ণ, কারণ bবস্তুর নিজস্ব রয়েছে b। আপনি আপনার স্ট্রিংফাই কলটিতে উভয়ই পেতে চাইবেন তবে আপনি মিস করবেনspam.b.b2 । এটা খারাপ.
রাফিন

1
@ আরফিন এটি সত্য, তবে এটি এমনকি কাম্য হতে পারে। আমি মনে করি ওপি যা চেয়েছিল তা কেবল নিশ্চিত করার জন্য messageএবং stackজেএসএনে অন্তর্ভুক্ত করা হয়েছিল।
felixfbecker

74

কেন কেউ অংশ নেওয়ার বিষয়ে কথা বলছে না , আমি তার উত্তর দেব।

কেন এটি JSON.stringifyএকটি খালি বস্তু ফেরায়?

> JSON.stringify(error);
'{}'

উত্তর

JSON.stringify () এর দস্তাবেজ থেকে ,

অন্যান্য সমস্ত অবজেক্টের উদাহরণগুলির জন্য (মানচিত্র, সেট, উইকম্যাপ এবং উইকসেট সহ) কেবলমাত্র তাদের অগণিত বৈশিষ্ট্যগুলি সিরিয়ালায়িত করা হবে।

এবং Errorঅবজেক্টের এর অগনিত গুণাবলী নেই, এ কারণেই এটি একটি খালি বস্তু মুদ্রণ করে।


4
অদ্ভুত কেউ এমনকি মাথা ঘামান না। যতক্ষণ না স্থির কাজগুলি আমি ধরে নিয়েছি :)
ইলিয়া চেরনোমর্ডিক

1
এই উত্তরের প্রথম অংশটি সঠিক নয়। JSON.stringifyএর replacerপ্যারামিটারটি ব্যবহার করার একটি উপায় রয়েছে ।
টড চাফি

1
@ টাড চ্যাফি এটি একটি ভাল বিষয়। আমি আমার উত্তর স্থির করেছি। দয়া করে এটি যাচাই করুন এবং এটি উন্নত করতে নির্দ্বিধায়। ধন্যবাদ।
সংঘিউন লি

52

বানরের প্যাচিং এড়াতে জোনাথনের দুর্দান্ত উত্তরটি পরিবর্তন করা:

var stringifyError = function(err, filter, space) {
  var plainObject = {};
  Object.getOwnPropertyNames(err).forEach(function(key) {
    plainObject[key] = err[key];
  });
  return JSON.stringify(plainObject, filter, space);
};

var error = new Error('testing');
error.detail = 'foo bar';

console.log(stringifyError(error, null, '\t'));

3
প্রথমবার আমি শুনেছি monkey patching:)
ক্রিস প্রিন্স

2
@ ক্রিসপ্রিন্স তবে এটি জাভাস্ক্রিপ্টে শেষবারের মতো হবে না! শুধু ভবিষ্যতের লোকদের তথ্যের জন্য, এখানে বানর প্যাচিংয়ের উইকিপিডিয়া । ( জোনাথনের উত্তরে ক্রিস যেমন বুঝতে পেরেছেন, আপনি সরাসরি একটি নতুন ফাংশন যুক্ত করছেন toJSON, সরাসরি Errorপ্রোটোটাইপে যা প্রায়শই দুর্দান্ত ধারণা নয় Maybe সম্ভবত অন্য কারও কাছে ইতিমধ্যে এটি রয়েছে যা চেক করে তবে আপনি জানেন না কী অন্যান্য সংস্করণ আছে যে বা কেউ অপ্রত্যাশিতভাবে পুলিশের পায়, বা অনুমান ত্রুটি প্রোটোটাইপ নির্দিষ্ট বৈশিষ্ট্য আছে, কিছু চড়াও পারে)
Ruffin

এটি দুর্দান্ত, তবে ত্রুটির স্ট্যাকটি বাদ দেয় (যা কনসোলে দেখানো হয়েছে)। বিশদ সম্পর্কে নিশ্চিত নয়, এটি যদি ভ্যু-সম্পর্কিত হয় বা কী, কেবল এটি উল্লেখ করতে চেয়েছিল।
ফিল্ড 294

23

এর জন্য একটি দুর্দান্ত নোড.জেএস প্যাকেজ রয়েছে: serialize-error

এটি ভালভাবে নেস্টেড ত্রুটিযুক্ত বস্তুগুলি পরিচালনা করে, আমার প্রকল্পে আমার আসলে যা আমার প্রয়োজন ছিল।

https://www.npmjs.com/package/serialize-error


না, তবে এটি করার জন্য এটি স্থানান্তরিত করা যেতে পারে। এই মন্তব্য দেখুন ।
আইএক্স 3

এটি সঠিক উত্তর। ত্রুটিগুলি সিরিয়ালাইজ করা একটি তুচ্ছ সমস্যা নয় এবং লাইব্রেরির লেখক (অনেকগুলি জনপ্রিয় প্যাকেজ সহ একটি দুর্দান্ত দেব) প্রান্তের কেসগুলি পরিচালনা করার জন্য উল্লেখযোগ্য পরিমাণে গিয়েছিলেন, যেমনটি README তে দেখা যায়: "কাস্টম বৈশিষ্ট্যগুলি সংরক্ষিত আছে Non অগণনীয় বৈশিষ্ট্যগুলি অ-গণনাযোগ্য (নাম, বার্তা, স্ট্যাক) রাখা হয় En
ড্যান ড্যাসকলেসকু

9

আপনি সেইগুলি অগণনীয় গুণাগুণকে কেবলমাত্র পুনরায় সংজ্ঞা দিতে পারেন ume

Object.defineProperty(Error.prototype, 'message', {
    configurable: true,
    enumerable: true
});

এবং stackসম্পত্তি সম্ভবত ।


9
আপনার মালিকানাধীন অবজেক্টগুলিকে পরিবর্তন করবেন না, এটি আপনার আবেদনের অন্যান্য অংশ এবং এর কারণ অনুসন্ধান করার জন্য সৌভাগ্য কামনা করতে পারে।
ফ্রেংতে

7

আমাদের একটি স্বেচ্ছাচারিত বস্তু শ্রেণিবিন্যাসকে সিরিয়ালকরণ করা দরকার, যেখানে শ্রেণিবদ্ধের মূল বা কোনও নেস্টেট বৈশিষ্ট্য ত্রুটির উদাহরণ হতে পারে।

আমাদের সমাধান ব্যবহার করতে ছিল replacerএর PARAM JSON.stringify(), যেমন:

function jsonFriendlyErrorReplacer(key, value) {
  if (value instanceof Error) {
    return {
      // Pull all enumerable properties, supporting properties on custom Errors
      ...value,
      // Explicitly pull Error's non-enumerable properties
      name: value.name,
      message: value.message,
      stack: value.stack,
    }
  }

  return value
}

let obj = {
    error: new Error('nested error message')
}

console.log('Result WITHOUT custom replacer:', JSON.stringify(obj))
console.log('Result WITH custom replacer:', JSON.stringify(obj, jsonFriendlyErrorReplacer))


5

উপরের উত্তরগুলির মধ্যে কোনওটিই ত্রুটির প্রোটোটাইপের বৈশিষ্ট্যগুলিকে যথাযথভাবে সিরিয়ালাইজ করে নি বলে মনে হয় (কারণ because getOwnPropertyNames() উত্তরাধিকারসূত্রে প্রাপ্ত বৈশিষ্ট্যগুলি অন্তর্ভুক্ত নয়)। প্রস্তাবিত উত্তরের একটির মতো আমিও বৈশিষ্ট্যগুলি নতুন করে সংজ্ঞায়িত করতে পারিনি।

এই সমাধানটি আমি নিয়ে এসেছি - এতে লোডাশ ব্যবহার করা হয় তবে আপনি সেই ফাংশনের জেনেরিক সংস্করণ দিয়ে লোডাশ প্রতিস্থাপন করতে পারেন।

 function recursivePropertyFinder(obj){
    if( obj === Object.prototype){
        return {};
    }else{
        return _.reduce(Object.getOwnPropertyNames(obj), 
            function copy(result, value, key) {
                if( !_.isFunction(obj[value])){
                    if( _.isObject(obj[value])){
                        result[value] = recursivePropertyFinder(obj[value]);
                    }else{
                        result[value] = obj[value];
                    }
                }
                return result;
            }, recursivePropertyFinder(Object.getPrototypeOf(obj)));
    }
}


Error.prototype.toJSON = function(){
    return recursivePropertyFinder(this);
}

আমি Chrome এ যা পরীক্ষা করেছি তা এখানে:

var myError = Error('hello');
myError.causedBy = Error('error2');
myError.causedBy.causedBy = Error('error3');
myError.causedBy.causedBy.displayed = true;
JSON.stringify(myError);

{"name":"Error","message":"hello","stack":"Error: hello\n    at <anonymous>:66:15","causedBy":{"name":"Error","message":"error2","stack":"Error: error2\n    at <anonymous>:67:20","causedBy":{"name":"Error","message":"error3","stack":"Error: error3\n    at <anonymous>:68:29","displayed":true}}}  

2

আমি লগ সংযোজনকারীদের জন্য একটি JSON ফর্ম্যাটে কাজ করছি এবং অনুরূপ সমস্যা সমাধানের চেষ্টা করে এখানে এসেছি। কিছুক্ষণ পরে, আমি বুঝতে পেরেছিলাম যে আমি কেবল নোডের কাজটি করতে পারি:

const util = require("util");
...
return JSON.stringify(obj, (name, value) => {
    if (value instanceof Error) {
        return util.format(value);
    } else {
        return value;
    }
}

1
এটি হওয়া উচিত instanceofএবং নাও হওয়া উচিত instanceOf
lakshman.pasala
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.