简体   繁体   English

如何在 JavaScript 中将普通 object 转换为另一种类型的实例

[英]How to cast a plain object as a instance of another type in JavaScript

I'm trying to store a session on disk for local development, and I'm running into a problem where the application expects me to return an instance of a Session and not an Object我正在尝试在磁盘上存储 session 以进行本地开发,但我遇到了一个问题,即应用程序希望我返回 Session 的实例而不是 Z497031794414A53B5435F9015ZAC1

function storeCallback(session) {
  console.log("storeCallback ", session);
  fs.writeFileSync("./session.json", JSON.stringify(session));
  return true;
}

function loadCallback(id) {
  console.log("loadCallback ", id);
  const session = fs.readFileSync("./session.json", "utf8");
  return JSON.parse(session);
}

The session look like this: session 看起来像这样:

Session {
   id: '0984e7db-ad80-4276-966d-9db54fac11c2',
   shop: 'swiftnextstep.myshopify.com',
   state: '113617456401679',
   isOnline: true
 }

Once I save and read back, it looks like this一旦我保存并读回,它看起来像这样

 {
   id: '0984e7db-ad80-4276-966d-9db54fac11c2',
   shop: 'swiftnextstep.myshopify.com',
   state: '113617456401679',
   isOnline: true
 }

And I get an error InternalServerError: Expected return to be instance of Session, but received instance of Object.我收到一个错误InternalServerError: Expected return to be instance of Session, but received instance of Object.

How can I cast/transform the object I'm parsing from storage into the expected Session type?如何将我正在从存储解析的 object 转换/转换为预期的 Session 类型?

JSON does not save a class, so what you get back when you read JSON is just a plain object with properties. JSON 不保存 class,所以当您阅读 JSON 时得到的只是具有属性的普通 ZA8CFDE6331BD59EB26ZAC6666 Usually, the way you reconstitute it into a class is that you create a constructor for your class that accepts that exact object you parsed from your JSON as a parameter to the constructor and then the constructor copies that data into the instance data for an instance of your class. Usually, the way you reconstitute it into a class is that you create a constructor for your class that accepts that exact object you parsed from your JSON as a parameter to the constructor and then the constructor copies that data into the instance data for an instance of你的 class。 Or, if you don't control the constructor, then you use whatever constructor there is, create a new object of that type, then set the properties you need to set from the object you parsed from your JSON.或者,如果您不控制构造函数,则使用任何构造函数,创建该类型的新 object,然后从您从 Z0ECD11C1D7A287401D148A23BBD7 解析的 object 设置您需要设置的属性。

It's possible to directly set the prototype on the object you got from parsing the JSON with Object.setPrototypeOf() , but I prefer using the constructor design because then if you have other properties or newer properties in a newer version of the code, that constructor can programmatically handle any missing properties with appropriate defaults. It's possible to directly set the prototype on the object you got from parsing the JSON with Object.setPrototypeOf() , but I prefer using the constructor design because then if you have other properties or newer properties in a newer version of the code, that constructor可以用适当的默认值以编程方式处理任何缺失的属性。 It's also often useful in your JSON to store a version number so if you change the format over time, you can know what version you're reading from disk and can have code that adapts to the older or newer version of JSON.在 JSON 中存储版本号通常也很有用,因此如果您随着时间的推移更改格式,您可以知道您正在从磁盘读取哪个版本,并且可以拥有适应旧版本或新版本 JSON 的代码。

Note, I also don't usually directly JSON.stringify() my class either because I may have state variables that don't really belong in the JSON. Note, I also don't usually directly JSON.stringify() my class either because I may have state variables that don't really belong in the JSON. Instead, I create a .toJSON() method and let that generate the JSON for me and then my code can control exactly what is and isn't in the JSON from my instance data.相反,我创建了一个.toJSON()方法并让它为我生成 JSON,然后我的代码可以从我的实例数据中准确控制 JSON 中的内容。

JavaScript doesn't really have nominative types for object values. JavaScript 实际上没有object值的主格类型 It does have prototypes which are reified (through Object.getPrototypeOf and Constructor.prototype ) as well as with instanceof .确实具有经过具体化的原型(通过Object.getPrototypeOfConstructor.prototype )以及instanceof It looks like Shopify's library is using instanceof or getProtoypeOf to determine if your parameter argument is a " Session " or not.看起来 Shopify 的库正在使用instanceofgetProtoypeOf来确定您的参数参数是否为“ Session ”。

Now, I'm not familiar with Shopify's library, but you can use the Session constructor - or create a clone of the object (which carries-over the prototype).现在,我不熟悉 Shopify 的库,但您可以使用Session构造函数 - 或创建 object 的克隆(继承原型)。 Try this:尝试这个:

function loadCallback(id) {
  console.log("loadCallback ", id);
  const sessionJson = fs.readFileSync("./session.json", "utf8");
  const sessionObj  = new Session(); // assuming the ctor has no parameters
  
  const session2 = Object.assign( sessionObj, sessionJson ); // copy `sessionJson`'s properties into `sessionObj`.

  return session2;
}

Session looks to be exported only from session.ts . Session 看起来只能从session.ts导出。 The constructor is empty, so that's not something you have to worry about, it's just an object with properties.构造函数是空的,所以你不必担心,它只是一个带有属性的 object。 To turn a non-Session into a Session, you should be able to just assign to properties of a Session.要将非会话转换为 Session,您应该能够只分配给 Session 的属性。

import { Session } from "@shopify/shopify-api/dist/auth/session/session";

function loadCallback(id) {
  console.log("loadCallback ", id);
  return Object.assign(
    new Session(),
    JSON.parse(fs.readFileSync("./session.json", "utf8")))
  );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM