import { JsonClassType, JsonProperty, ObjectMapper, JsonIdentityInfo, ObjectIdGenerator } from 'jackson-js';

@JsonIdentityInfo({generator: ObjectIdGenerator.PropertyGenerator, property: 'id', scope: 'User'})
class User {
  @JsonProperty() @JsonClassType({type: () => [Number]})
  id: number;
  @JsonProperty() @JsonClassType({type: () => [String]})
  email: string;
  @JsonProperty() @JsonClassType({type: () => [String]})
  firstname: string;
  @JsonProperty() @JsonClassType({type: () => [String]})
  lastname: string;

  @JsonProperty()
  @JsonClassType({type: () => [Array, [Item]]})
  items: Item[] = [];

  constructor(id: number, email: string, firstname: string, lastname: string) {
    this.id = id;
    this.email = email;
    this.firstname = firstname;
    this.lastname = lastname;
  }
}

@JsonIdentityInfo({generator: ObjectIdGenerator.PropertyGenerator, property: 'id', scope: 'Item'})
class Item {
  @JsonProperty() @JsonClassType({type: () => [Number]})
  id: number;
  @JsonProperty() @JsonClassType({type: () => [String]})
  name: string;

  @JsonProperty()
  @JsonClassType({type: () => [User]})
  owner: User;

  constructor(id: number, name: string, @JsonClassType({type: () => [User]}) owner: User) {
    this.id = id;
    this.name = name;
    this.owner = owner;
  }
}

const user = new User(1, 'john.alfa@gmail.com', 'John', 'Alfa');
const item1 = new Item(1, 'Book', user);
const item2 = new Item(2, 'Computer', user);
user.items.push(...[item1, item2]);
const objectMapper = new ObjectMapper();
const jsonData = objectMapper.stringify<User>(user);
console.log(jsonData);
// {"items":[{"id":1,"name":"Book","owner":1},{"id":2,"name":"Computer","owner":1}],"id":1,"email":"john.alfa@gmail.com","firstname":"John","lastname":"Alfa"}
const userParsed = objectMapper.parse<User>(jsonData, {mainCreator: () => [User]});
console.log(userParsed);
/*
<ref *1> User {
  items: [
    Item { id: 1, name: 'Book', owner: [Circular *1] },
    Item { id: 2, name: 'Computer', owner: [Circular *1] }
  ],
  id: 1,
  email: 'john.alfa@gmail.com',
  firstname: 'John',
  lastname: 'Alfa'
}
*/