JSON.stringify() - object's custom serializer - javascript

Let's say I have an object:
const a = {
foo: 123,
bar: 'example'
}
This object is a part of many other objects i.e.
const b = {
a: a,
anotherField: "example"
}
Actually, I'm using TypeScript and all these objects are of the same class which I believe isn't important.
After serializing the b object to JSON I need to get this string (i.e. I just get the foo field from a):
{ a: 123, anotherField: "example" }
What is the easiest and most elegant way to tell JSON.stringify() how to convert the a object to a string?
Probably something similar to what Python allows.

You could define toJSON in a.
If an object being stringified has a property named toJSON whose value is a function, then the toJSON() method customizes JSON stringification behavior: instead of the object being serialized, the value returned by the toJSON() method when called will be serialized.
(source: MDN)
For example:
class A {
constructor(foo, bar) {
this.foo = foo;
this.bar = bar;
}
toJSON() {
return this.foo;
}
}
const a = new A(123, "some name");
const b = {
a: a,
anotherField: "example"
};
console.log(JSON.stringify(b)); // "{"a":123,"anotherField":"example"}"

You could use the replacer while stringifying:
const result = JSON.stringify(b, (k, v) => v && v.stringify() || v);
That way you can easily add a custom stringification to a:
const a = {
foo: 123,
bar: 'example',
stringify() { return this.foo; }
}

Related

Jest: expect object not to have property

I want to write a test that asserts a given object does not have certain properties.
Say I have a function
function removeFooAndBar(input) {
delete input.foo;
delete input.bar;
return input;
}
Now I want to write a test:
describe('removeFooAndBar', () => {
it('removes properties `foo` and `bar`', () => {
const data = {
foo: 'Foo',
bar: 'Bar',
baz: 'Baz',
};
expect(removeFooAndBar(data))
.toEqual(expect.objectContaining({
baz: 'Baz', // what's left
foo: expect.not.exists() // pseudo
bar: undefined // this doesn't work, and not what I want
}));
});
});
What's the proper way to assert this?
Update after the discussion in the comments
You can use expect.not.objectContaining(). This approach works fine but has one unfortunate edge case: It matches when the property exists, but is undefined or null. To fix this you can explicitly add those values to be included in the check. You need the jest-extended package for the toBeOneOf() matcher.
expect({foo: undefined}).toEqual(expect.not.objectContaining(
{foo: expect.toBeOneOf([expect.anything(), undefined, null])}
));
An example with nested props that fails:
const reallyAnything = expect.toBeOneOf([expect.anything(), undefined, null]);
expect({foo: undefined, bar: {baz: undefined}}).toEqual(
expect.not.objectContaining(
{
foo: reallyAnything,
bar: {baz: reallyAnything},
}
)
);
Original answer
What I'd do is to explicitly check whether the object has a property named bar or foo.
delete data.foo;
delete data.bar;
delete data.nested.property;
expect(data).not.toHaveProperty('bar');
expect(data).not.toHaveProperty('foo');
expect(data.nested).not.toHaveProperty('property');
// or
expect(data).not.toHaveProperty('nested.property');
Or make this less repeating by looping over the properties that will be removed.
const toBeRemoved = ['foo', 'bar'];
toBeRemoved.forEach((prop) => {
delete data[prop];
expect(data).not.toHaveProperty(prop);
});
However, the loop approach isn't too great for possible nested objects.
I believe what you are looking for is expect.not.objectContaining()
expect(data).toEqual(expect.not.objectContaining({foo: 'Foo', bar: 'Bar'}));
expect.not.objectContaining(object) matches any received object that
does not recursively match the expected properties. That is, the
expected object is not a subset of the received object. Therefore, it
matches a received object which contains properties that are not in
the expected object. - Jest Documentation
This answer is a paraphrase of the accepted answer. It is added only because of this exact suggestion to the accepted answer was rejected.
You can explicitly check whether the object has a property named bar or foo.
delete data.foo;
delete data.bar;
expect(data).not.toHaveProperty('bar');
expect(data).not.toHaveProperty('foo');
For nested properties:
delete data.nested.property;
expect(data.nested).not.toHaveProperty('property');
// or
expect(data).not.toHaveProperty('nested.property');
Or make this less repeating by looping over the properties that will be removed.
const toBeRemoved = ['foo', 'bar', 'nested.property'];
toBeRemoved.forEach((prop) => {
expect(data).not.toHaveProperty(prop);
});
However, the loop approach isn't too great for possible nested objects. What you are looking for is expect.not.objectContaining().
expect({baz: 'some value'}).toEqual(expect.not.objectContaining(
{foo: expect.anything()}
));
This approach works fine but has one unfortunate edge case: It matches when the property exists, but is undefined or null:
expect({foo: undefined}).toEqual(expect.not.objectContaining(
{foo: expect.anything()}
));
would also match. To fix this you can explicitly add those values to be included in the check. You need the jest-extended package for the toBeOneOf() matcher.
expect({foo: undefined}).toEqual(expect.not.objectContaining(
{foo: expect.toBeOneOf([expect.anything(), undefined, null])}
));
An example with nested props that, expectedly, fails:
const reallyAnything = expect.toBeOneOf([expect.anything(), undefined, null]);
expect({foo: undefined, bar: {baz: undefined}}).toEqual(
expect.not.objectContaining(
{
foo: reallyAnything,
bar: {baz: reallyAnything},
}
)
);
can you check the result? example?
const result = removeFooAndBar(data)
expect(result.foo).toBeUndefined()
expect(result.bar).toBeUndefined()
you can check initially that the properties were there.
The other option is to extend the expect function: https://jestjs.io/docs/expect#expectextendmatchers
expect.extend({
withUndefinedKeys(received, keys) {
const pass = keys.every((k) => typeof received[k] === 'undefined')
if (pass) {
return {
pass: true,
}
}
return {
message: () => `expected all keys ${keys} to not be defined in ${received}`,
pass: false,
}
},
})
expect({ baz: 'Baz' }).withUndefinedKeys(['bar', 'foo'])
I'd just try because you know the data value to use it:
const data = {...};
const removed = {...data};
delete removed.foo;
delete removed.bar;
expect(removeFooAndBar(data)).toEqual(removed);
Edit 1: Because of Jest's expect.not, try something like:
const removed = removeFooAndBar(data);
expect(removed).not.toHaveProperty('foo');
expect(removed).not.toHaveProperty('bar');
expect(removed).toHaveProperty('baz');
Do not check object.foo === undefined as others suggest.
This will result to true if the object has the property foo set to undefined
eg.
const object = {
foo: undefined
}
Have you tried use the hasOwnProperty function?
this will give you the following results
const object = {foo: ''};
expect(Object.prototype.hasOwnProperty.call(object, 'foo')).toBe(true);
object.foo = undefined;
expect(Object.prototype.hasOwnProperty.call(object, 'foo')).toBe(true);
delete object.foo;
expect(Object.prototype.hasOwnProperty.call(object, 'foo')).toBe(false);
It is possible to check whether an object has selected fields (expect.objectContaining) and in a separate assertion whether it does not have selected fields (expect.not.objectContaining). However, it is not possible, by default, to check these two things in one assertion, at least I have not heard of it yet.
Goal: create a expect.missing matcher similar to standard expect.any or expect.anything which will check if the object does not have the selected field and can be used alongside matchers of existing fields.
My attempts to reach this goal are summarized below, maybe someone will find them useful or be able to improve upon them.
I point out that this is a proof of concept and it is possible that there are many errors and cases that I did not anticipate.
AsymmetricMatchers in their current form lack the ability to check their context, for example, when checking the expect.any condition for a in the object { a: expect.any(String), b: [] }, expect.any knows nothing about the existence of b, the object in which a is a field or even that the expected value is assigned to the key a. For this reason, it is not enough to create only expect.missing but also a custom version of expect.objectContaining, which will be able to provide the context for our expect.missing matcher.
expect.missing draft:
import { AsymmetricMatcher, expect } from 'expect'; // npm i expect
class Missing extends AsymmetricMatcher<void> {
asymmetricMatch(actual: unknown): boolean {
// By default, here we have access only to the actual value of the selected field
return !Object.hasOwn(/* TODO get parent object */, /* TODO get property name */);
}
toString(): string {
return 'Missing';
}
toAsymmetricMatcher(): string {
return this.toString(); // how the selected field will be marked in the diff view
}
}
Somehow the matcher above should be given context: object and property name. We will create a custom expect.objectContaining - let's call it expect.objectContainingOrNot:
class ObjectContainingOrNot extends AsymmetricMatcher<Record<string, unknown>> {
asymmetricMatch(actual: any): boolean {
const { equals } = this.getMatcherContext();
for (const [ property, expected ] of Object.entries(this.sample)) {
const received = actual[ property ];
if (expected instanceof Missing) {
Object.assign(expected, { property, propertyContext: actual });
} // TODO: this would be sufficient if we didn't care about nested values
if (!equals(received, expected)) {
return false;
}
}
return true;
}
toString(): string {
// borrowed from .objectContaining for sake of nice diff printing
return 'ObjectContaining';
}
override getExpectedType(): string {
return 'object';
}
}
Register new matchers to the expect:
expect.missing = () => new Missing();
expect.objectContainingOrNot = (sample: Record<string, unknown>) =>
new ObjectContainingOrNot(sample);
declare module 'expect' {
interface AsymmetricMatchers {
missing(): void;
objectContainingOrNot(expected: Record<string, unknown>): void;
}
}
Full complete code:
import { AsymmetricMatcher, expect } from 'expect'; // npm i expect
class Missing extends AsymmetricMatcher<void> {
property?: string;
propertyContext?: object;
asymmetricMatch(_actual: unknown): boolean {
if (!this.property || !this.propertyContext) {
throw new Error(
'.missing() expects to be used only' +
' inside .objectContainingOrNot(...)'
);
}
return !Object.hasOwn(this.propertyContext, this.property);
}
toString(): string {
return 'Missing';
}
toAsymmetricMatcher(): string {
return this.toString();
}
}
class ObjectContainingOrNot extends AsymmetricMatcher<Record<string, unknown>> {
asymmetricMatch(actual: any): boolean {
const { equals } = this.getMatcherContext();
for (const [ property, expected ] of Object.entries(this.sample)) {
const received = actual[ property ];
assignPropertyCtx(actual, property, expected);
if (!equals(received, expected)) {
return false;
}
}
return true;
}
toString(): string {
return 'ObjectContaining';
}
override getExpectedType(): string {
return 'object';
}
}
// Ugly but is able to assign context for nested `expect.missing`s
function assignPropertyCtx(ctx: any, key: PropertyKey, value: unknown): unknown {
if (value instanceof Missing) {
return Object.assign(value, { property: key, propertyContext: ctx });
}
const newCtx = ctx?.[ key ];
if (Array.isArray(value)) {
return value.forEach((e, i) => assignPropertyCtx(newCtx, i, e));
}
if (value && (typeof value === 'object')) {
return Object.entries(value)
.forEach(([ k, v ]) => assignPropertyCtx(newCtx, k, v));
}
}
expect.objectContainingOrNot = (sample: Record<string, unknown>) =>
new ObjectContainingOrNot(sample);
expect.missing = () => new Missing();
declare module 'expect' {
interface AsymmetricMatchers {
objectContainingOrNot(expected: Record<string, unknown>): void;
missing(): void;
}
}
Usage examples:
expect({ baz: 'Baz' }).toEqual(expect.objectContainingOrNot({
baz: expect.stringMatching(/^baz$/i),
foo: expect.missing(),
})); // pass
expect({ baz: 'Baz', foo: undefined }).toEqual(expect.objectContainingOrNot({
baz: 'Baz',
foo: expect.missing(),
})); // fail
// works with nested!
expect({ arr: [ { id: '1' }, { no: '2' } ] }).toEqual(expect.objectContainingOrNot({
arr: [ { id: '1' }, { no: expect.any(String), id: expect.missing() } ],
})); // pass
When we assume that the field is also missing when it equals undefined ({ a: undefined } => a is missing) then the need to pass the context to expect.missing disappears and the above code can be simplified to:
import { AsymmetricMatcher, expect } from 'expect';
class ObjectContainingOrNot extends AsymmetricMatcher<Record<string, unknown>> {
asymmetricMatch(actual: any): boolean {
const { equals } = this.getMatcherContext();
for (const [ property, expected ] of Object.entries(this.sample)) {
const received = actual[ property ];
if (!equals(received, expected)) {
return false;
}
}
return true;
}
toString(): string {
return `ObjectContaining`;
}
override getExpectedType(): string {
return 'object';
}
}
expect.extend({
missing(actual: unknown) {
// However, it still requires to be used only inside
// expect.objectContainingOrNot.
// expect.objectContaining checks if the objects being compared
// have matching property names which happens before the value
// of those properties reaches this matcher
return {
pass: actual === undefined,
message: () => 'It seems to me that in the' +
' case of this matcher this message is never used',
};
},
});
expect.objectContainingOrNot = (sample: Record<string, unknown>) =>
new ObjectContainingOrNot(sample);
declare module 'expect' {
interface AsymmetricMatchers {
missing(): void;
objectContainingOrNot(expected: Record<string, unknown>): void;
}
}
// With these assumptions, assertion below passes
expect({ baz: 'Baz', foo: undefined }).toEqual(expect.objectContainingOrNot({
baz: 'Baz',
foo: expect.missing(),
}));
It was fun, have a nice day!
I would just try:
expect(removeFooAndBar(data))
.toEqual({
baz: 'Baz'
})

Typescript - Create custom type from common properties of an Array of object

I have an array of objects, which have a common key "foo" and I am trying to create a custom type out of this property. I am not looking for its value that I can get from a reduce but more its Type. Here is a link to the TypeScript playground with a reproduced example and the expected output Type I need to retrieve:
class Object1 {
static foo = { reducer_one: { a: 1 } }
object_1_method() { }
}
class Object2 {
static foo = { reducer_two: { b: 2 } }
object_2_method() { }
}
class Object3 {
static foo = { reducer_three: { c: 3 } }
object_3_method() { }
}
const myArray = [Object1, Object2, Object3 ];
const reducers = myArray.reduce((acc, cur) => {
return {
...acc,
...cur.foo
}
}, {});
const myArray = [Object1, Object2, Object3 ];
I am trying to get a reduced object type gathering all the different foo properties of all the initial objects in the array.
const finalObject = {
reducer_one: {...},
reducer_two: {...},
reducer_three: {...}
}
I tried to reduce the array to an object with the objects' respective foo property in order to retrieve its type but the output type of the reduce remains an empty object.
Thanks in advance for your help. Hope the description of the issue is clear enough
You will pretty much need to use a type assertion to tell the compiler what type reducers is going to be. Let's call this type ReducedType with the understanding that we will have to define it at some point.
If you use Array.reduce() or any other method to walk through an array and add properties gradually, the compiler can't really follow what's happening. See
How can i move away from a Partial<T> to T without casting in Typescript for a similar issue.
You could try to use the Object.assign() function to do this all at once:
const maybeReducers =
Object.assign({}, ...myArray.map(cur => cur.foo)) // any
but the TypeScript library typings for Object.assign() operating on a variadic number of inputs just returns a value of the any type, which doesn't help you either.
Let's stick with reduce():
const reducers = myArray.reduce((acc, cur) => {
return {
...acc,
...cur.foo
}
}, {} as ReducedType);
So we're asserting that the initial {} value passed in is ReducedType. This assertion is sort of a lie that eventually becomes true.
So how do we compute ReducedType from the type of myArray? Let's look at myArray with [the TypeScript typeof operator]:
type MyArray = typeof myArray
// type MyArray = (typeof Object1 | typeof Object2 | typeof Object3)[]
First we want to get the type of the elements of that array. Since you get elements from an array by indexing into them with a numeric index, we can take the MyArray type and index into it with the number type:
type MyArrayElement = MyArray[number]
// type MyArrayElement = typeof Object1 | typeof Object2 | typeof Object3
That's a union of the three class constructor types. From there we want to get the type of each union member's foo property. We can do that with another indexed access (which distributes across unions):
type MyArrayElementFooProp = MyArrayElement["foo"]
/* type MyArrayElementFooProp = {
reducer_three: {
c: number;
};
} | {
reducer_one: {
a: number;
};
} | {
reducer_two: {
b: number;
};
} */
So that is looking closer to what you want... except it's a union and you really want the intersection of them, since your ReducedType should have all of those properties.
(And no, I don't know why the compiler chooses to order the union with three at the front. It doesn't affect type safety at any rate.)
There is a way to transform a union into an intersection using TypeScript's distributive conditional types and conditional type inference, shown here without additional explanation (see the other q/a pair)
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
type IntersectionOfFoos = UnionToIntersection<MyArrayElementFooProp>
/* type IntersectionOfFoos = {
reducer_three: {
c: number;
};
} & {
reducer_one: {
a: number;
};
} & {
reducer_two: {
b: number;
};
} */
This is exactly the type we want, although it isn't represented too pleasantly. A type like {x: 0} & {y: 1} is equivalent to but less pleasing than {x: 0; y: 1}. We can use a simple mapped type to convert from the former form to the latter:
type ReducedType =
{ [K in keyof IntersectionOfFoos]: IntersectionOfFoos[K] }
/* type ReducedType = {
reducer_three: {
c: number;
};
reducer_one: {
a: number;
};
reducer_two: {
b: number;
};
} */
And we can stop there if you want. It is of course possible to put this together in a single type alias, although it's less obvious what we're doing:
type ReducedType =
typeof myArray[number]["foo"] extends infer F ?
(F extends unknown ? (x: F) => void : never) extends
(x: infer I) => void ?
{ [K in keyof I]: I[K] }
: never : never
/* type ReducedType = {
reducer_three: {
c: number;
};
reducer_one: {
a: number;
};
reducer_two: {
b: number;
};
} */
So there you go, now the compiler knows the type of reducers strongly enough to let you index into it:
console.log(reducers.reducer_one.a.toFixed(2)); // 1.00
console.log(reducers.reducer_two.b.toFixed(3)); // 2.000
console.log(reducers.reducer_three.c.toFixed(4)); // 3.0000
Playground link to code
const finalObject = myArray.reduce((obj, clazz) => {
Object.keys(clazz.foo).forEach(prop => {
obj[prop] = clazz.foo[prop];
});
return obj;
}, {});

Typescript: Convert union of similar objects to object type

How to transform union of similar objects to object type using TypeScript typings?
Input
type I = {
key: 'foo',
value: Foo,
} | {
key: 'bar',
value: Bar,
};
Output
type O = {
foo: Foo,
bar: Bar,
};
I am not sure it is possible. But who knows?
Note that the task is not a duplicate to that.
In TypeScript 4.1 this is a straightforward mapped type with key remapping. You can iterate over each member T of the I union (it's a union, not an intersection) and look up the key/value types: T['key'] for the key and T['value'] for the value. Like this:
type O = { [T in I as T['key']]: T['value'] };
/* type O = {
foo: Foo;
bar: Bar;
} */
Playground link to code

Replace the type of an object property in a Flow type

Let's say we have defined a very simple object type:
type A = {
foo: string,
bar: number,
// ... many other properties
};
Now we'd like to define a variant of this type, just replacing the type of foo by ?string:
type A2 = {
foo: ?string,
bar: number,
// ... many other properties, with the same types as in A
};
How can that be done, without having to define the whole type again?
It'd be enough if the answer only worked in the particular case of replacing property type T by ?T, since that is my most frequent problem.
I can think of two solutions:
1) a parametric type alias
type Parametric<T> = {
foo: T,
bar: number,
// ... many other properties
};
type A = Parametric<string>;
type B = Parametric<?string>;
2) intersections
type Base = {
bar: number,
// ... many other properties
};
type A = Base & { foo: string };
type B = Base & { foo: ?string };
I would use the spread operator with exact types (introduced in flow v0.42.0).
type A = {|
foo: string,
bar: number,
// ... many other properties
|}
type A2 = {
...A,
foo: ?string
}
Note: You need to use an exact type for A (the {| ... |} syntax). This is because of how flow handles unsealed (not exact) types when spreading.
For nested properties, you can use the $PropertyType<T, k> utility.
type Type1 = {
prop1: string,
prop2: {
a?: string,
b?: number,
}
}
type Type2 = {
...Type1,
prop2: {
...$PropertyType<Type1, "prop2">,
c: boolean,
}
}
const obj: Type2 = {
prop1: "foo",
prop2: {
a: "foo",
c: true,
}
}
const {
prop2: {
a,
b,
c
}
}: Type2 = obj;
if (c === true) {
// do something
}
flow.org/try

convert javascript plain object into model class instance

I need to implement small ODM like feature. I get plain javascript object from database, and I need to convert it into my model class instance. Let's assume model looks like:
class Model{
constructor(){
this.a = '777';
---- whole bunch of other things ---
}
print(){
console.log(this.a);
}
}
So I need convert var a = {b:999, c:666} to instance of model and being able to call a.print() after, and when a.print() executed 777 should be placed in console. How to do that?
There have a simple method. Just assign the object to instance(this)
class Model
{
constructor(obj){
Object.assign(this, obj)
}
print(){
console.log(this.a);
}
}
let obj = {a: 'a', b: 'b', c: 'c'}
let m = new Model(obj)
console.log(m)
m.print() // 'a'
If I understand the question correctly, you can export a factory function and make use of Object.assign to extend your base Model:
// Export the factory function for creating Model instances
export default const createModel = function createModel(a) {
const model = new Model();
return Object.assign(model, a);
};
// Define your base class
class Model {
constructor() {
this.a = 777;
}
print() {
console.log(this.a, this.b, this.c)
}
}
And call it like:
const myModel = createModel({ b: 999, c: 666 });
myModel.print();
Babel REPL Example
Or, of course, you could forego the factory and pass a in as a parameter (or rest parameters) to the constructor but it depends on your preferred coding style.
I would suggest rewriting your class to store all its properties in a single JS object this.props and accept this object in its constructor:
class Model {
constructor (props = this.initProps()) {
this.props = props
// other stuff
}
initProps () {
return {a: '777'}
}
print () {
console.log(this.props.a)
}
}
Then you'll be able to store this.props in your database as a plain JS object and then use it to easily recreate corresponding class instance:
new Model(propsFromDatabase)
Though, if you don't want to move all properties to this.props, you could use Object.assign to keep your object plain:
class Model {
constructor (props = this.initProps()) {
Object.assign(this, props)
// other stuff
}
initProps () {
return {a: '777'}
}
print () {
console.log(this.a)
}
}
But I would recommend using the former approach, because it'll keep you safe from name collisions.
If you need to typecast more consistently, you can also create your own typecast function like generic function
function typecast(Class, obj) {
let t = new Class()
return Object.assign(t,obj)
}
// arbitrary class
class Person {
constructor(name,age) {
this.name = name
this.age = age
}
print() {
console.log(this.name,this.age)
}
}
call it to typecast any object to any class instance like
let person = typecast(Person,{name:'Something',age:20})
person.print() // Something 20
How about this?:
var a = Object.create(Model.prototype, {
b: {
enumerable: true, // makes it visible for Object.keys()
writable: true, // makes the property writable
value: 999
}, c: {
value: 666
}
});
You'd be basically creating a new instance of Model from it's prototype and assigning your new properties to it. You should be able to call print as well.
You could have a static Model.from or Model.parse method, that returns a new Model with those properties:
class Model {
static defaults = { a: 777, b: 888, c: 999, d: 111, e: 222 };
constructor() {
const { defaults } = Model;
for (const key in defaults) this[key] = defaults[key];
}
print() {
console.log(this.a);
}
static from(data) {
const { defaults } = Model;
return Object.assign(
new Model(),
defaults,
Object.fromEntries(
Object.entries(data).filter(([key]) => key in defaults)
)
);
}
}
const data = {
a: "a", b: "b", c: "c", ajkls: "this wont be included"
};
const myModel = Model.from(data);
console.log("myModel =", myModel);
console.log("myModel instanceof Model:", myModel instanceof Model);
console.log("myModel.print():")
myModel.print();
Just like G_hi3's answer, but it "automates" the creation of the properties object
function Model() {
this.a = '777';
}
Model.prototype.print = function(){
console.log(this.a);
}
// Customize this if you don't want the default settings on the properties object.
function makePropertiesObj(obj) {
return Object.keys(obj).reduce(function(propertiesObj, currentKey){
propertiesObj[currentKey] = {value: obj[currentKey]};
return propertiesObj;
}, {}); // The object passed in is the propertiesObj in the callback
}
var data = {a: '888'};
var modelInstance = Object.create(Model.prototype, makePropertiesObj(data));
// If you have some non trivial initialization, you would need to call the constructor.
Model.call(modelInstance);
modelInstance.print(); // 888
First declare a class in which you want to convert JSON:
class LoginResponse {
constructor(obj) {
Object.assign(this, obj);
}
access_token;
token_type;
expires_in;
}
Now convert the general javascript object into your desired class object:
const obj = {
access_token: 'This is access token1',
token_type: 'Bearer1',
expires_in: 123,
};
let desiredObject = new LoginResponse(obj);
console.log(desiredObject);
Output will be:
LOG {"access_token": "This is access token1", "expires_in": 123, "token_type": "Bearer1"}

Categories