আমি কীভাবে JSON অবজেক্টকে টাইপস্ক্রিপ্ট ক্লাসে কাস্ট করব


393

আমি একটি রিমোট REST সার্ভার থেকে একটি JSON অবজেক্ট পড়েছি। এই JSON অবজেক্টে টাইপস্ক্রিপ্ট শ্রেণীর সমস্ত বৈশিষ্ট্য রয়েছে (নকশার দ্বারা)। আমি কীভাবে জাসন বস্তুটি কোনও টাইপের ভেরিতে নিক্ষেপ করব?

আমি কোনও টাইপস্ক্রিপ্ট ভেরি পপুলি করতে চাই না (যেমন কোনও কনস্ট্রাক্টর রয়েছে যা এই জেএসওএন অবজেক্ট নেয়)। এটি বড় এবং উপ-অবজেক্টের মাধ্যমে সাব-অবজেক্ট এবং সম্পত্তি দ্বারা সম্পত্তি দ্বারা সমস্ত কিছু অনুলিপি করাতে অনেক সময় লাগবে।

আপডেট: তবে আপনি এটি কোনও টাইপ স্ক্রিপ্ট ইন্টারফেসে কাস্ট করতে পারেন !


আপনার জেএসওএন জাভা ক্লাস ব্যবহার করে ম্যাপ করা হয়েছে এমন ক্ষেত্রে আপনি টাইপস্ক্রিপ্ট ইন্টারফেস তৈরি করতে github.com/vojtechhabarta/tyypecript-generator ব্যবহার করতে পারেন
ভোজটা

আমি একটি ছোট কাস্টিং লাইব্রেরি কোড করেছি: সালফার
ব্লগ.আজুরওয়েবসাইটস / টাইপসক্রিপ্ট -মিনি-কাস্টিক-

1
JSON অবজেক্ট = জাভাস্ক্রিপ্ট অবজেক্ট নোটেশন অবজেক্ট। সেখানে পর্যাপ্ত বস্তু নেই, আমি বললাম ভাল পরিমাপের জন্য আমরা আরও কয়েকটা রেখেছি।
বাগ-এ-লট


আপনার অবজেক্টটি সংজ্ঞায়িত করতে প্রোটোটাইপ টাইপস্ক্রিপ্ট ক্লাস তৈরি করা প্রকৃত উত্পাদন কোডকে ক্ষতিগ্রস্থ করবে না। সংকলিত জেএস ফাইলটি একবার দেখুন, সমস্ত সংজ্ঞা মুছে ফেলা হবে, যেহেতু তারা জেএসের অংশ নয়।
FisNaN

উত্তর:


167

আপনি অ্যাজাক্স অনুরোধ থেকে একটি প্রোটোটাইপাল জাভাস্ক্রিপ্ট / টাইপস্ক্রিপ্ট শ্রেণীর উদাহরণে সহজ-সরল-জাভাস্ক্রিপ্ট ফলাফল কাস্ট করতে পারবেন না। এটি করার জন্য বেশ কয়েকটি কৌশল রয়েছে এবং সাধারণত কপি করা ডেটা জড়িত। আপনি শ্রেণীর উদাহরণ তৈরি না করলে এর কোনও পদ্ধতি বা বৈশিষ্ট্য থাকবে না। এটি একটি সাধারণ জাভাস্ক্রিপ্ট অবজেক্ট থাকবে।

আপনি যদি কেবলমাত্র ডেটা নিয়েই কাজ করে থাকেন তবে আপনি কেবল একটি ইন্টারফেসে কাস্ট করতে পারেন (এটি নিখুঁতভাবে একটি সংকলন সময় কাঠামো হিসাবে) তবে এর জন্য আপনাকে এমন কোনও টাইপস্ক্রিপ্ট ক্লাস ব্যবহার করতে হবে যা ডেটা উদাহরণ ব্যবহার করে এবং সেই ডেটা দিয়ে অপারেশন করে।

ডেটা অনুলিপি করার কয়েকটি উদাহরণ:

  1. AJAX JSON অবজেক্টটি বিদ্যমান অবজেক্টে অনুলিপি করা হচ্ছে
  2. JSON স্ট্রিংটিকে জাভাস্ক্রিপ্টের একটি বিশেষ বস্তুর প্রোটোটাইপে পার্স করুন

মোটকথা, আপনি ঠিক:

var d = new MyRichObject();
d.copyInto(jsonResult);

আমি আপনার উত্তরের সাথে একমত একটি সংযোজন হিসাবে, যদিও আমি এখনই এটি সন্ধান এবং এটি এখনই পরীক্ষা করার জায়গায় নেই তবে আমি মনে করি এই দুটি পদক্ষেপকে পরম হিসাবে একটি ওয়েকআপ ফাংশন দিয়ে মিলিত করা যেতে পারে JSON.parse()। উভয় এখনও করা প্রয়োজন, কিন্তু সিন্ট্যাক্টিকভাবে তারা একত্রিত করা যেতে পারে।
JAAulde

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

অবশ্যই আমি যে উত্তরটির সন্ধান করছিলাম তা অবশ্যই নয় :( কৌতূহলের বাইরে এটি কেন? জাভাস্ক্রিপ্ট যেভাবে কাজ করে তা এইভাবে করা উচিত বলে মনে হয়
ডেভিড থিলেন

না, এটি টাইপস্ক্রিপ্টে কাজ করে না কারণ জাভাস্ক্রিপ্টে এটি করার কোনও সহজ উপায় নেই।
ওয়্যার্ডপ্রাইরি

1
কী সম্পর্কেObject.setPrototypeOf
পেটাহ

102

আমার একই সমস্যা ছিল এবং আমি একটি লাইব্রেরি পেয়েছি যা কাজটি করে: https://github.com/pleerock/class-transformer

এটি এর মতো কাজ করে:

let jsonObject = response.json() as Object;
let fooInstance = plainToClass(Models.Foo, jsonObject);
return fooInstance;

এটি নেস্টেড বাচ্চাদের সমর্থন করে তবে আপনাকে আপনার শ্রেণীর সদস্যকে সাজাতে হবে।


14
এই উজ্জ্বল ছোট গ্রন্থাগারটি এটিকে সর্বনিম্ন প্রচেষ্টা দিয়ে নিখুঁতভাবে সমাধান করেছে ( @Typeযদিও আপনার টীকাগুলি ভুলে যাবেন না )। এই উত্তরটি আরও creditণের দাবিদার।
বেনি বোট্টেমা

ওহ বাহ! এই গ্রন্থাগারটি আপনার প্রয়োজনীয় সমস্ত কিছু এত ছোট নয়, এমনকি আপনাকে @ ট্রান্সফর্ম ডেকরেটারের সাহায্যে রূপান্তরটি নিয়ন্ত্রণ করতে দেয়: ডি
দিয়েগো ফার্নান্দো মারিলো ভ্যালেনসি

3
নোট করুন যে এই লাইব্রেরি সবে আর রক্ষণাবেক্ষণ করা হয়। এটি Angular5 + এর সাথে আর কাজ করে না এবং যেহেতু তারা আর টানার অনুরোধগুলি মার্জ করে না, তাই আমি মনে করি না যে তারা শীঘ্রই যে কোনও সময়ে কাজ করবে on যদিও এটি একটি দুর্দান্ত গ্রন্থাগার।
কেন্টর

অ্যাঙ্গুলার 5 + (এটি আসলে একটি কৌণিক বাগ) এর জন্য একটি কার্যকারিতা রয়েছে
পাক

2
এটি কৌণিক 6 এ ঠিক কাজ করে (কমপক্ষে আমার ব্যবহারের ক্ষেত্রে যা আক্ষরিক JSON <=> শ্রেণীর মানচিত্র তৈরি করতে পারে)
ttd

54

টাইপস্ক্রিপ্ট এ আপনি একটি করতে পারেন কোনও ইন্টারফেস এবং জেনেরিকগুলি ব্যবহার করে টাইপ :

var json = Utilities.JSONLoader.loadFromFile("../docs/location_map.json");
var locations: Array<ILocationMap> = JSON.parse(json).location;

যেখানে ILocationMap আপনার ডেটার আকার বর্ণনা করে। এই পদ্ধতির সুবিধাটি হ'ল আপনার জেএসওনে আরও বেশি বৈশিষ্ট্য থাকতে পারে তবে আকৃতিটি ইন্টারফেসের শর্তাদি সন্তুষ্ট করে।

আমি আশা করি এটি সাহায্য করবে!


49
এফওয়াইআই: এটি একটি প্রকারের দাবি, castালাই নয়।
ওয়্যার্ডপ্রাইরি

6
কোনও প্রকারের দাবি এবং কাস্টের মধ্যে পার্থক্যের জন্য এখানে দেখুন ।
স্টিফান হ্যাঙ্ক

7
ইউটিলিটিস.জে জেএসএনআলওডার কোথায় পাব?
HypeXR

22
তবে এর কোনও পদ্ধতি থাকবে না, যেমনটি উত্তরে উল্লেখ করা হয়েছে।
মার্টন কল

1
@ স্টেফানহানকে দেখে মনে হচ্ছে ইউআরএল কিছুটা পরিবর্তন হয়েছে: "টাইপ
অ্যাসেরেশন

37

আপনি যদি ES6 ব্যবহার করছেন তবে এটি ব্যবহার করে দেখুন:

class Client{
  name: string

  displayName(){
    console.log(this.name)
  }
}

service.getClientFromAPI().then(clientData => {

  // Here the client data from API only have the "name" field
  // If we want to use the Client class methods on this data object we need to:
  let clientWithType = Object.assign(new Client(), clientData)

  clientWithType.displayName()
})

তবে দুঃখের সাথে এই উপায়টি নীড়ের বস্তুটিতে কাজ করবে না


4
তারা এটি টাইপস্ক্রিপ্টে চেয়েছিল।
joe.feser

HI @ joe.feser, আমি ES6 উল্লেখ করেছি কারণ এইভাবে 'অবজেক্ট.স্যাসাইন' পদ্ধতিটি প্রয়োজনীয়।
মাইগকোডার

1
যদি ডিফল্ট কনস্ট্রাক্টর নিখোঁজ থাকে Object.create(MyClass.prototype)তবে সম্পূর্ণরূপে কনস্ট্রাক্টরকে বাইপাস করে লক্ষ্য উদাহরণটি তৈরি করা যেতে পারে ।
মার্সেলো

সীমাবদ্ধতা মধ্যে দেখতে নেস্টেড বস্তু সম্পর্কে ব্যাখ্যা stackoverflow.com/questions/22885995/...
মাইকেল Freidgeim

28

আমি একটি টাইপস্ক্রিপ্ট ক্লাসে জেএসএন-এর জেনেরিক কাস্টিং সম্পর্কিত একটি খুব আকর্ষণীয় নিবন্ধ পেয়েছি:

http://cloudmark.github.io/Json-Mapping/

আপনি নিম্নলিখিত কোড সহ শেষ:

let example = {
                "name": "Mark", 
                "surname": "Galea", 
                "age": 30, 
                "address": {
                  "first-line": "Some where", 
                  "second-line": "Over Here",
                  "city": "In This City"
                }
              };

MapUtils.deserialize(Person, example);  // custom class

20

টিএলডিআর: ওয়ান লাইনার

// This assumes your constructor method will assign properties from the arg.
.map((instanceData: MyClass) => new MyClass(instanceData));

বিস্তারিত উত্তর

আমি অবজেক্ট.অ্যাসাইন পদ্ধতির সুপারিশ করব না , কারণ এটি আপনার শ্রেণীর উদাহরণটিকে অপ্রাসঙ্গিক বৈশিষ্ট্যগুলি (পাশাপাশি সংজ্ঞায়িত ক্লোজারগুলি) দিয়ে ক্লাস করতে পারে যা ক্লাসের মধ্যেই ঘোষণা করা হয়নি।

আপনি যে শ্রেণীতে ডিসরিয়ালাইজ করার চেষ্টা করছেন, আমি নিশ্চিত করব যে আপনি যে বৈশিষ্ট্যগুলি deserialized করতে চান তা সংজ্ঞায়িত হয়েছে (নাল, খালি অ্যারে, ইত্যাদি)। প্রাথমিক মানগুলির সাথে আপনার বৈশিষ্ট্যগুলি সংজ্ঞায়িত করে যখন শ্রেণি সদস্যদের মানগুলি নির্ধারণের জন্য পুনরাবৃত্তি করার চেষ্টা করার সময় আপনি তাদের দৃশ্যমানতাটি প্রকাশ করেন (নীচের পদ্ধতিটি deserialize দেখুন)।

export class Person {
  public name: string = null;
  public favoriteSites: string[] = [];

  private age: number = null;
  private id: number = null;
  private active: boolean;

  constructor(instanceData?: Person) {
    if (instanceData) {
      this.deserialize(instanceData);
    }
  }

  private deserialize(instanceData: Person) {
    // Note this.active will not be listed in keys since it's declared, but not defined
    const keys = Object.keys(this);

    for (const key of keys) {
      if (instanceData.hasOwnProperty(key)) {
        this[key] = instanceData[key];
      }
    }
  }
}

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

এটি এইচটিএসপি রেসির মতো কিছুতে কীভাবে ব্যবহার করা যায় তা এখানে ...

this.http.get(ENDPOINT_URL)
  .map(res => res.json())
  .map((resp: Person) => new Person(resp) ) );

যদি tslint / আদর্শ আর্গুমেন্ট টাইপটি বেমানান হওয়ার অভিযোগ করে, কেবল কৌনিক বন্ধনী ব্যবহার করে আর্গুমেন্টটিকে একই ধরণের মধ্যে ফেলে দিন <YourClassName>, উদাহরণস্বরূপ:

const person = new Person(<Person> { name: 'John', age: 35, id: 1 });

আপনার যদি শ্রেণীর সদস্য থাকে যা নির্দিষ্ট ধরণের (যেমন: অন্য শ্রেণীর উদাহরণ), তবে আপনি সেগুলি গেটার / সেটার পদ্ধতির মাধ্যমে টাইপ করা ইভেন্টগুলিতে কাস্ট করতে পারেন।

export class Person {
  private _acct: UserAcct = null;
  private _tasks: Task[] = [];

  // ctor & deserialize methods...

  public get acct(): UserAcct {
    return this.acct;
  }
  public set acct(acctData: UserAcct) {
    this._acct = new UserAcct(acctData);
  }

  public get tasks(): Task[] {
    return this._tasks;
  }

  public set tasks(taskData: Task[]) {
    this._tasks = taskData.map(task => new Task(task));
  }
}

উপরের উদাহরণটি Acct এবং তাদের নিজ শ্রেণীর উদাহরণগুলিতে কাজের তালিকা উভয়কেই deserialize করবে।


আমি এই ত্রুটি বার্তাটি পেয়েছি: টাইপ করুন '{নাম: স্ট্রিং, বয়স: সংখ্যা, আইডি: নম্বর}' 'ব্যক্তি' টাইপতে রূপান্তর করা যায় না। সম্পত্তি 'আইডি' ব্যক্তিগত 'টাইপ ব্যক্তি' তবে 'টাইপ নয়' নাম: স্ট্রিং, বয়স: সংখ্যা, আইডি: সংখ্যা} '
utiq

এনামদের সাথে আমার এটি কীভাবে ব্যবহার করা উচিত? আমাকে কি নির্দিষ্ট ধরণের পদ্ধতির ব্যবহার করতে হবে এবং এর জন্য গেটর এবং সেটার যুক্ত করতে হবে?
তাদিজা বাগারিć

@ টিমোথিপ্রেজ আপনি কখন কাজগুলি সেট করবেন?
কে

আমি অনুরূপ কিছু করার চেষ্টা করেছি কিন্তু আমি যখন কনসোল.লগ করি তখন আমার কাজগুলি অ্যারে খালি থাকে।
কে

এটি সংকলনের জন্য আমাকে শ্রেণিতে একটি সূচক স্বাক্ষর যোগ করতে হয়েছিল: রফতানি শ্রেণি ব্যক্তি {[কী: স্ট্রিং]: যে কোনও (...)}
অসীমভ

18

ধরে নিচ্ছি যে জেসনের আপনার টাইপ স্ক্রিপ্ট শ্রেণীর মতো একই বৈশিষ্ট্য রয়েছে, আপনার জেসন বৈশিষ্ট্যগুলি আপনার টাইপ স্ক্রিপ্ট অবজেক্টে অনুলিপি করতে হবে না। আপনাকে কেবল আপনার টাইপস্ক্রিপ্ট অবজেক্টটি কনস্ট্রাক্টরে জেসন ডেটা পাস করার জন্য তৈরি করতে হবে।

আপনার এজাক্স কলব্যাকে, আপনি একটি সংস্থা পেয়েছেন:

onReceiveCompany( jsonCompany : any ) 
{
   let newCompany = new Company( jsonCompany );

   // call the methods on your newCompany object ...
}

সেই কাজটি করার জন্য:

1) আপনার টাইপস্ক্রিপ্ট ক্লাসে এমন একজন কনস্ট্রাক্টর যুক্ত করুন যা জেসন ডেটাটিকে প্যারামিটার হিসাবে নেয়। সেই কনস্ট্রাক্টরে আপনি আপনার জসন বস্তুকে jQuery এর সাথে প্রসারিত করুন:$.extend( this, jsonData)। ex। এক্সটেনড জাভাস্ক্রিপ্ট প্রোটোটাইপগুলি রাখার সময় জসন অবজেক্টের বৈশিষ্ট্য যুক্ত করার অনুমতি দেয়।

2) নোট করুন লিঙ্কযুক্ত বস্তুর জন্য আপনাকে একই কাজ করতে হবে। উদাহরণস্বরূপ কর্মচারীদের ক্ষেত্রে, আপনি কর্মীদের জন্য জসন ডেটার অংশ গ্রহণ করে একটি কন্সট্রাক্টরও তৈরি করেন। আপনি জসন কর্মীদের টাইপ স্ক্রিপ্ট কর্মচারী অবজেক্টগুলিতে অনুবাদ করতে $ .map কল করেন।

export class Company
{
    Employees : Employee[];

    constructor( jsonData: any )
    {
        $.extend( this, jsonData);

        if ( jsonData.Employees )
            this.Employees = $.map( jsonData.Employees , (emp) => {
                return new Employee ( emp );  });
    }
}

export class Employee
{
    name: string;
    salary: number;

    constructor( jsonData: any )
    {
        $.extend( this, jsonData);
    }
}

টাইপস্ক্রিপ্ট ক্লাস এবং জসন অবজেক্টের সাথে ডিল করার সময় এটিই আমার সেরা সমাধান।


আমি ইন্টারফেস প্রয়োগ এবং পরিচালনা রক্ষার চেয়ে এই সমাধানটিকে প্রাধান্য দিই, কারণ আমার অ্যাঙ্গুলার 2 অ্যাপ্লিকেশনগুলিতে একটি সত্যিকারের অ্যাপ্লিকেশন মডেল রয়েছে যা আমার অ্যাপ্লিকেশনটি গ্রাহিত ওয়েব সার্ভিসের মডেলের চেয়ে আলাদা হতে পারে। এটিতে ব্যক্তিগত ডেটা এবং গণনা করা বৈশিষ্ট্য থাকতে পারে।
অ্যান্টনি ব্রেনেলিয়ার

7
কৌণিক প্রকল্পগুলিতে জিকিউরি ব্যবহার করা একটি ভয়ানক ধারণা। এবং যদি আপনার মডেলগুলিতে সেগুলির একটি গুচ্ছ থাকে তবে সেগুলি আর মডেল নয়।
Davor

1
@ প্রিয় আপনি পজো বা মডেল বলতে চান? POJO (মূলত প্লেইন অবজেক্টস) এর কোনও ফাংশন নেই, অন্যদিকে মডেলটি বিস্তৃত শব্দ, এবং এতে ভান্ডার অন্তর্ভুক্ত রয়েছে। POJO এর বিপরীতে রিপোজিটরি প্যাটার্নটি ফাংশন সম্পর্কে, তবে এটি এখনও মডেল।
ফোরসবার্গ

@ পছন্দসই: কৌণিক প্রকল্পগুলিতে জ্যাকুয়ারি ব্যবহার করা ততক্ষণ খারাপ ধারণা নয় যতক্ষণ না আপনি এটি ডিওএম কে কাজে লাগানোর জন্য ব্যবহার করবেন না, এটি সত্যই একটি ভয়ঙ্কর ধারণা। আমি আমার কৌণিক প্রকল্পগুলির জন্য আমার যে কোনও গ্রন্থাগার প্রয়োজন তা ব্যবহার করি এবং jQuery এর জন্য এটি কোনও বিকল্প নয় কারণ আমার প্রকল্পটি সিগন্যালআর ব্যবহার করে যা এটি নির্ভর করে। ক্লাসগুলির ক্ষেত্রে, এখন জাভাস্ক্রিপ্ট ES6 দ্বারা ব্যবহৃত হয়, ডেটা মেমরির মধ্যে যেভাবে ডেটা সংরক্ষণ করা হয় সেভাবে এনক্যাপুলেট করে এমন বৈশিষ্ট্যগুলির সাথে ডেটা অ্যাক্সেস করা হয়। নির্মাতাদের জন্য, একটি সঠিক উপায় রয়েছে যা কারখানাগুলি ব্যবহার করে।
অ্যান্থনি ব্রেনেলিয়ার

ওপি স্পষ্টভাবে বিশ্রামের জন্য সরল ডেটা মডেলগুলি সম্পর্কে। ছেলেরা, আপনি এটি অযথা জটিল করে তুলছেন। এবং হ্যাঁ, আপনি অতিরিক্ত স্টাফের জন্য জ্যাকুরি ব্যবহার করতে পারেন, তবে আপনি এর 1% ব্যবহার করতে একটি বিশাল গ্রন্থাগার আমদানি করছেন। এটি একটি কোড গন্ধ আমি যদি কখনও দেখেছি।
Davor

18

আপনি সার্ভার থেকে প্রাপ্ত JSON অবজেক্টের টাইপস্ক্রিপ্টের ইন্টারফেস বৈশিষ্ট্যের প্রত্যাশিত (পঠনযোগ্যভাবে সামঞ্জস্যপূর্ণ) আছে কিনা তা স্বয়ংক্রিয়ভাবে যাচাই করার জন্য এখনও কিছুই নেই। তবে আপনি ব্যবহারকারী-সংজ্ঞায়িত টাইপ গার্ড ব্যবহার করতে পারেন

নিম্নলিখিত ইন্টারফেস এবং একটি নির্বোধ জসন বস্তু বিবেচনা (এটি কোনও ধরণের হতে পারে):

interface MyInterface {
    key: string;
 }

const json: object = { "key": "value" }

তিনটি সম্ভাব্য উপায়:

উ: ভেরিয়েবলের পরে দৃser় সংজ্ঞা বা সরল স্ট্যাটিক Typeালাই টাইপ করুন

const myObject: MyInterface = json as MyInterface;

বি ভেরিয়েবলের আগে এবং হীরার মধ্যে সাধারণ স্ট্যাটিক castালাই

const myObject: MyInterface = <MyInterface>json;

সি উন্নত গতিশীল castালাই, আপনি নিজেকে বস্তুর কাঠামো পরীক্ষা করে দেখুন check

function isMyInterface(json: any): json is MyInterface {
    // silly condition to consider json as conform for MyInterface
    return typeof json.key === "string";
}

if (isMyInterface(json)) {
    console.log(json.key)
}
else {
        throw new Error(`Expected MyInterface, got '${json}'.`);
}

আপনি এখানে এই উদাহরণ দিয়ে খেলতে পারেন

মনে রাখবেন যে এখানে isMyInterfaceঅসুবিধাটি ফাংশনটি লেখার জন্য । আমি আশা করি টিএস দ্রুত বা পরে রানটাইমের সময় জটিল টাইপ রফতানি করার জন্য একটি সাজসজ্জা যুক্ত করবে এবং প্রয়োজনের সময় রানটাইম অবজেক্টের কাঠামোটি পরীক্ষা করতে দেবে। আপাতত, আপনি হয় একটি জসন স্কিমা যাচাইকারী ব্যবহার করতে পারেন যা উদ্দেশ্য প্রায় একই বা এই রানটাইম টাইপ চেক ফাংশন জেনারেটর


1
আপনার উত্তরটি শীর্ষে থাকা উচিত বলে আমি মনে করি
আফজালেক্স

স্পষ্টভাবে. এটি সেরা উত্তর যা সরাসরি টিএস ওয়েবসাইটে নির্ভর করে।
বুড়াক করাকুş

15

আমার ক্ষেত্রে এটি কাজ করে। আমি অবজেক্ট.সেসাইন (লক্ষ্য, উত্স ...) ফাংশন ব্যবহার করেছি । প্রথমে সঠিক অবজেক্টটি তৈরি করা, তারপরে জেসন অবজেক্ট থেকে ডেটাটি টার্গেটে অনুলিপি করে। উদাহরণ:

let u:User = new User();
Object.assign(u , jsonUsers);

এবং ব্যবহারের আরও উন্নত উদাহরণ। অ্যারে ব্যবহার করে একটি উদাহরণ।

this.someService.getUsers().then((users: User[]) => {
  this.users = [];
  for (let i in users) {
    let u:User = new User();
    Object.assign(u , users[i]);
    this.users[i] = u;
    console.log("user:" + this.users[i].id);
    console.log("user id from function(test it work) :" + this.users[i].getId());
  }

});

export class User {
  id:number;
  name:string;
  fullname:string;
  email:string;

  public getId(){
    return this.id;
  }
}

আপনার ব্যক্তিগত সম্পত্তি থাকলে কী হয়?
প্রসংশাথ

কারণ jsonUser অবজেক্টটি কোনও ব্যবহারকারী শ্রেণি নয়। অপারেশন ছাড়াই অবজেক্ট.সেসাইন (ইউ, জসন ইউজার); আপনি getId () ফাংশনটি ব্যবহার করতে পারবেন না। কেবলমাত্র নিয়োগের পরে আপনি একটি বৈধ ব্যবহারকারী অবজেক্ট পাবেন যাতে আপনি getId () ফাংশনটি ব্যবহার করতে পারেন। GetId () ফাংশনটি কেবল উদাহরণস্বরূপ যা অপারেশন সফল হয়েছিল।
আদম 111 পি

আপনি টেম্পের ভার এড়িয়ে যেতে পারেন - ঠিক করুনthis.users[i] = new User(); Object.assign(this.users[i], users[i])
সাইপটাস

বা আরও ভাল ফেরতের মানটি ব্যবহার করুন:this.users[i] = Object.assign(new User(), users[i]);
সাইপটাস

এই দীর্ঘ সংস্করণটি কেবল ব্যাখ্যার জন্য। আপনি নিজের পছন্দ অনুযায়ী কোডটি ছোট করতে পারেন :)
অ্যাডাম 111 পি

6

যদিও এটি প্রতি সেটিং notালছে না; আমি দরকারী বিকল্প হিসাবে https://github.com/JohnWhiteTB/TypeedJSON খুঁজে পেয়েছি ।

@JsonObject
class Person {
    @JsonMember
    firstName: string;

    @JsonMember
    lastName: string;

    public getFullname() {
        return this.firstName + " " + this.lastName;
    }
}
var person = TypedJSON.parse('{ "firstName": "John", "lastName": "Doe" }', Person);

person instanceof Person; // true
person.getFullname(); // "John Doe"

1
এটি ingালাই নয়, এটি আসলে কী করে?
ড্যানিয়েল

1
এই সমাধানটির জন্য অজস্র টিকা দরকার। সত্যিই কি এর চেয়ে সহজ উপায় নেই?
জেপিএনট্যাড্রাগন

3

আপনি আপনার টাইপগুলির একটি তৈরি করতে পারেন interface( SomeType) এবং এতে বস্তুটি কাস্ট করতে পারেন।

const typedObject: SomeType = <SomeType> responseObject;

3

আপনি যদি আপনার জসনকে কোনও টাইপ স্ক্রিপ্ট শ্রেণিতে ফেলে দিতে চান এবং ফলস্বরূপ অবজেক্টটিতে আপনার উদাহরণ পদ্ধতিগুলি উপলব্ধ রয়েছে Object.setPrototypeOfযেমন আমি কোড স্নিপেট বেলোতে করেছি:

Object.setPrototypeOf(jsonObject, YourTypescriptClass.prototype)

2

বেশিরভাগ সঠিক, তবে খুব দক্ষ উত্তর নয় এমন একটি পুরানো প্রশ্ন। এটি আমার প্রস্তাব:

একটি বেস ক্লাস তৈরি করুন যার মধ্যে init () পদ্ধতি এবং স্ট্যাটিক কাস্ট পদ্ধতি রয়েছে (একটি একক বস্তু এবং অ্যারের জন্য)। স্থির পদ্ধতিগুলি যে কোনও জায়গায় হতে পারে; বেস ক্লাস এবং init () সহ সংস্করণ পরে সহজ এক্সটেনশানগুলির অনুমতি দেয়।

export class ContentItem {
    // parameters: doc - plain JS object, proto - class we want to cast to (subclass of ContentItem)
    static castAs<T extends ContentItem>(doc: T, proto: typeof ContentItem): T {
        // if we already have the correct class skip the cast
        if (doc instanceof proto) { return doc; }
        // create a new object (create), and copy over all properties (assign)
        const d: T = Object.create(proto.prototype);
        Object.assign(d, doc);
        // reason to extend the base class - we want to be able to call init() after cast
        d.init(); 
        return d;
    }
    // another method casts an array
    static castAllAs<T extends ContentItem>(docs: T[], proto: typeof ContentItem): T[] {
        return docs.map(d => ContentItem.castAs(d, proto));
    }
    init() { }
}

অনুরূপ মেকানিক ( অ্যাসাইন () সহ ) @ অ্যাডাম 111 পি পোস্টে উল্লেখ করা হয়েছে। এটি করার জন্য অন্য একটি (আরও সম্পূর্ণ) উপায়। @ টিমোথি পেরেজ নির্ধারিত সমালোচনা () করলেও, তবে এটি এখানে পুরোপুরি উপযুক্ত।

উদ্ভূত (বাস্তব) শ্রেণি প্রয়োগ করুন:

import { ContentItem } from './content-item';

export class SubjectArea extends ContentItem {
    id: number;
    title: string;
    areas: SubjectArea[]; // contains embedded objects
    depth: number;

    // method will be unavailable unless we use cast
    lead(): string {
        return '. '.repeat(this.depth);
    }

    // in case we have embedded objects, call cast on them here
    init() {
        if (this.areas) {
            this.areas = ContentItem.castAllAs(this.areas, SubjectArea);
        }
    }
}

এখন আমরা পরিষেবা থেকে পুনরুদ্ধার করা কোনও বস্তু নিক্ষেপ করতে পারি:

const area = ContentItem.castAs<SubjectArea>(docFromREST, SubjectArea);

সাবজেক্টআরিয়া সামগ্রীর সমস্ত শ্রেণিবিন্যাসের সঠিক শ্রেণি থাকবে।

একটি ব্যবহারের কেস / উদাহরণ; একটি কৌণিক পরিষেবা তৈরি করুন (আবার বিমূর্ত বেস শ্রেণি):

export abstract class BaseService<T extends ContentItem> {
  BASE_URL = 'http://host:port/';
  protected abstract http: Http;
  abstract path: string;
  abstract subClass: typeof ContentItem;

  cast(source: T): T {
    return ContentItem.castAs(source, this.subClass);
  }
  castAll(source: T[]): T[] {
    return ContentItem.castAllAs(source, this.subClass);
  }

  constructor() { }

  get(): Promise<T[]> {
    const value = this.http.get(`${this.BASE_URL}${this.path}`)
      .toPromise()
      .then(response => {
        const items: T[] = this.castAll(response.json());
        return items;
      });
    return value;
  }
}

ব্যবহার খুব সহজ হয়ে যায়; একটি অঞ্চল পরিষেবা তৈরি করুন:

@Injectable()
export class SubjectAreaService extends BaseService<SubjectArea> {
  path = 'area';
  subClass = SubjectArea;

  constructor(protected http: Http) { super(); }
}

( h ) পরিষেবাটি প্রাপ্ত পদ্ধতি সাবজেক্টআরিয়া অবজেক্টস হিসাবে সম্পূর্ণ কাস্ট করা একটি অ্যারের প্রতিশ্রুতি ফিরিয়ে দেবে (পুরো শ্রেণিবিন্যাস)

এখন বলুন, আমাদের আরও একটি ক্লাস রয়েছে:

export class OtherItem extends ContentItem {...}

সঠিক শ্রেণিতে ডেটা এবং ক্যাসেট পুনরুদ্ধার করে এমন একটি পরিষেবা তৈরি করা যেমন সহজ:

@Injectable()
export class OtherItemService extends BaseService<OtherItem> {
  path = 'other';
  subClass = OtherItem;

  constructor(protected http: Http) { super(); }
}

2

একটি ইন্টারফেস থেকে বর্ধিত একটি বর্গ ব্যবহার করুন।

তারপর:

Object.assign(
                new ToWhat(),
                what
              )

এবং সেরা:

Object.assign(
                    new ToWhat(),
                    <IDataInterface>what
                  )

টুওয়াত ডেটা ইন্টারফেসের নিয়ামক হয়ে ওঠে।


1

https://jvilk.com/MakeTypes/

আপনার জন্য প্রক্সি তৈরি করতে আপনি এই সাইটটি ব্যবহার করতে পারেন। এটি একটি শ্রেণী তৈরি করে এবং আপনার ইনপুট JSON অবজেক্টকে বিশ্লেষণ ও বৈধ করতে পারে।


0

লেটে টিএসে আপনি এটি করতে পারেন:

const isMyInterface = (val: any): val is MyInterface => {
  if (!val) { return false; }
  if (!val.myProp) { return false; }
  return true;
};

এবং এই মত ব্যবহারকারীর চেয়ে:

if (isMyInterface(data)) {
 // now data will be type of MyInterface
}

0

আমি একটি অনুরূপ প্রয়োজনে দৌড়ে। আমি এমন কিছু চেয়েছিলাম যা আমাকে জেএসএন থেকে / / এএসপি থেকে সহজেই রূপান্তর দেবে যা নির্দিষ্ট ক্লাস সংজ্ঞা থেকে / আরইএসটি এপি কল থেকে আসে। আমি যে সমাধানগুলি পেয়েছি তা অপ্রতুল বা আমার ক্লাসের কোডটি পুনরায় লেখার জন্য এবং টীকাগুলি বা সিমিলার যুক্ত করার উদ্দেশ্যে তৈরি হয়েছিল।

আমি জেএসওন এর মতো কিছু চাইছিলাম যা জেএসওএন অবজেক্টগুলিতে / থেকে ক্লাসকে সিরিয়ালাইজ / ডিসরিয়ালাইজ করতে জাভাতে ব্যবহৃত হয়।

পরবর্তী প্রয়োজনের সাথে মিশ্রিত করে, যে রূপান্তরকারীটি জেএসেও কাজ করবে, আমি নিজের প্যাকেজটি লিখতে শেষ করেছি।

এটি যদিও, ওভারহেড একটি সামান্য বিট। তবে যখন এটি শুরু হয় এটি যুক্ত করা এবং সম্পাদনা করা খুব সুবিধাজনক।

আপনি এইটির সাথে মডিউলটি আরম্ভ করবেন:

  1. রূপান্তর স্কিমা - ক্ষেত্রগুলির মধ্যে মানচিত্র তৈরি করার অনুমতি দেয় এবং রূপান্তর কীভাবে হবে তা নির্ধারণ করে
  2. ক্লাস মানচিত্র অ্যারে
  3. রূপান্তর ফাংশন মানচিত্র - বিশেষ রূপান্তর জন্য।

তারপরে আপনার কোডগুলিতে, আপনি আরম্ভিত মডিউলটি এর মতো ব্যবহার করেন:

const convertedNewClassesArray : MyClass[] = this.converter.convert<MyClass>(jsonObjArray, 'MyClass');

const convertedNewClass : MyClass = this.converter.convertOneObject<MyClass>(jsonObj, 'MyClass');

বা, জেএসএন-তে:

const jsonObject = this.converter.convertToJson(myClassInstance);

এনপিএম প্যাকেজে এই লিঙ্কটি ব্যবহার করুন এবং মডিউলটির সাথে কীভাবে কাজ করবেন তার বিশদ বিবরণ: json-class-রূপান্তরকারী

এটি
কৌণিক ব্যবহারের জন্য এটিতে মোড়ানো : কৌণিক-জসন-শ্রেণি-রূপান্তরকারী


0

ক্লাস কনস্ট্রাক্টরের মতো বস্তুটি পাস করুন; কোন সম্মেলন বা চেক নেই

interface iPerson {
   name: string;
   age: number;
}

class Person {
   constructor(private person: iPerson) { }

   toString(): string {
      return this.person.name + ' is ' + this.person.age;
   }  
}


// runs this as // 
const object1 = { name: 'Watson1', age: 64 };
const object2 = { name: 'Watson2' };            // age is missing

const person1 = new Person(object1);
const person2 = new Person(object2 as iPerson); // now matches constructor

console.log(person1.toString())  // Watson1 is 64
console.log(person2.toString())  // Watson2 is undefined

0

আপনি এই এনপিএম প্যাকেজটি ব্যবহার করতে পারেন। https://www.npmjs.com/package/class-converter

এটি ব্যবহার করা সহজ, উদাহরণস্বরূপ:

class UserModel {
  @property('i')
  id: number;

  @property('n')
  name: string;
}

const userRaw = {
  i: 1234,
  n: 'name',
};

// use toClass to convert plain object to class
const userModel = toClass(userRaw, UserModel);
// you will get a class, just like below one
// const userModel = {
//   id: 1234,
//   name: 'name',
// }

0

ব্যক্তিগতভাবে আমি এটিকে বিস্মিত করে দেখছি যে টাইপস্ক্রিপ্ট কোনও অবজেক্টের সংজ্ঞাটি প্রাপ্ত অবজেক্টের ধরণটি নির্দিষ্ট করার অনুমতি দেয় না। যেহেতু এটি প্রকৃতপক্ষে ক্ষেত্রে দেখা যাচ্ছে, আমি অন্যান্য ভাষাগুলির সাথে যা করেছি তা করব, এবং তা হচ্ছে আমি JSON অবজেক্টটিকে শ্রেণি সংজ্ঞা থেকে আলাদা করব এবং শ্রেণি সংজ্ঞাটি JSON অবজেক্টটিকে তার একমাত্র ডেটা সদস্য হিসাবে ব্যবহার করবে ।

আমি বয়লারপ্লেট কোডকে তুচ্ছ করি, তাই আমার পক্ষে এটি টাইপ সংরক্ষণের সময় কমপক্ষে কোডের কমপক্ষে পছন্দসই ফলাফলটিতে পৌঁছানোর বিষয়।

নিম্নলিখিত JSON অবজেক্ট স্ট্রাকচার সংজ্ঞা বিবেচনা করুন - এগুলি আপনি শেষ পয়েন্টে কী পাবেন তা সেগুলি কেবল কাঠামোর সংজ্ঞা, কোনও পদ্ধতি নেই।

interface IAddress {
    street: string;
    city: string;
    state: string;
    zip: string;
}

interface IPerson {
    name: string;
    address: IAddress;
}

যদি আমরা উপরেরটি অবজেক্ট অরিয়েন্টেড পদগুলিতে চিন্তা করি তবে উপরের ইন্টারফেসগুলি ক্লাস নয় কারণ তারা কেবল একটি ডেটা স্ট্রাকচারকে সংজ্ঞায়িত করে। ওও পদগুলির একটি শ্রেণি ডেটা এবং এটিতে পরিচালিত কোডটিকে সংজ্ঞায়িত করে।

সুতরাং আমরা এখন একটি ক্লাস সংজ্ঞায়িত করি যা ডেটা এবং এতে পরিচালিত কোড নির্দিষ্ট করে ...

class Person {
    person: IPerson;

    constructor(person: IPerson) {
        this.person = person;
    }

    // accessors
    getName(): string {
        return person.name;
    }

    getAddress(): IAddress {
        return person.address;
    }

    // You could write a generic getter for any value in person, 
    // no matter how deep, by accepting a variable number of string params

    // methods
    distanceFrom(address: IAddress): float {
        // Calculate distance from the passed address to this persons IAddress
        return 0.0;
    }
}

এবং এখন আমরা কেবল আইপারসন কাঠামোর সাথে মানিয়ে নিতে যে কোনও বস্তুটি পাস করতে পারি এবং আমাদের পথে যেতে পারি ...

   Person person = new Person({
            name: "persons name",
            address: {
                street: "A street address",
                city: "a city",
                state: "a state",
                zip: "A zipcode"
            }
        });

একই ফ্যাশনে আমরা এখন আপনার শেষ পয়েন্টে প্রাপ্ত অবজেক্টটি এর লাইনের সাথে কিছু দিয়ে প্রক্রিয়া করতে পারি ...

Person person = new Person(req.body);    // As in an object received via a POST call

person.distanceFrom({ street: "Some street address", etc.});

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


0

'হিসাবে' ঘোষণা হিসাবে ব্যবহার করুন:

const data = JSON.parse(response.data) as MyClass;

এই কৌশলটি এই উত্তরটিতে দু'বছর আগে থেকেই উল্লেখ করা হয়েছিল , এবং অন্যত্র যেমন আলোচনা করা হয়েছে, তেমন ঘোষণা করা যেতে পারে এমন কোনও কার্য যুক্ত করে না MyClass
হেরেটিক বানর

-1

এটি একটি সহজ এবং সত্যই ভাল বিকল্প

let person = "{"name":"Sam","Age":"30"}";

const jsonParse: ((key: string, value: any) => any) | undefined = undefined;
let objectConverted = JSON.parse(textValue, jsonParse);

এবং তারপর আপনার হবে

objectConverted.name

-1

আমি এই লাইব্রেরিটি এখানে ব্যবহার করেছি: https://github.com/pleerock/class-transformer

<script lang="ts">
    import { plainToClass } from 'class-transformer';
</script>

বাস্তবায়ন:

private async getClassTypeValue() {
  const value = await plainToClass(ProductNewsItem, JSON.parse(response.data));
}

কখনও কখনও আপনাকে প্লেটটোক্লাসের জন্য JSON মানগুলি পার্স করতে হবে তা বুঝতে যে এটি একটি JSON ফর্ম্যাট করা ডেটা


'ক্লাস-ট্রান্সফরমার' গ্রন্থাগার ইতিমধ্যে উপরে অন্যান্য উত্তরে পরামর্শ দেওয়া হয় stackoverflow.com/a/40042282/52277
মাইকেল Freidgeim

-1

আমি সীমান্তে অ্যাঙ্গুলার 6 এবং ব্যাকএন্ডে স্প্রিং বুট অ্যাপ্লিকেশন ব্যবহার করছি যা জাভা অবজেক্টগুলিকে রিটার্ন দেয়। আমাকে যা করতে হবে তা হল কৌণিক অ্যাপ্লিকেশনটিতে একটি অনুরূপ শ্রেণি সংজ্ঞায়িত করতে হবে যার মিলের বৈশিষ্ট্য রয়েছে এবং তারপরে আমি অবজেক্টটিকে একটি কৌণিক শ্রেণীর অবজেক্ট হিসাবে গ্রহণ করতে পারি ( নীচের উদাহরণে কোম্পানিরূপী কমপ )।

উদাহরণস্বরূপ নীচের সামনের শেষ কোডটি দেখুন। যদি আরও কিছু স্পষ্টতার প্রয়োজন হয় তবে আমাকে মন্তব্যে জানান।

  createCompany() {
    let company = new Company();
    company.name = this.companyName;

    this.companyService.createCompany(company).subscribe(comp => {
       if (comp !== null) {
        this.employerAdminCompany = comp as Company;
      }
    });
  }

যেখানে সংস্থাটি বসন্ত বুট অ্যাপ্লিকেশনটিতে একটি সত্তা বস্তু এবং এটি কৌণিকের একটি শ্রেণি।

export class Company {
    public id: number;
    public name: string;
    public owner: User;
    public locations: Array<Location>;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.