How to handle dynamic payloads in Node.js?

Asked

Viewed 38 times

-1

Hello, I would like to know what would be the best way to model the receipt of payloads with dynamic data, IE, I can sometimes receive a request with 3 fields, other, with 5, etc.

For example, in the same endpoint I can receive requests like:

{
  "nome": "Juninho",
  "dataNascimento": "26/01/2000"
}

Or

{
  "nome": "Maria",
  "sobrenome": "Joaquina",
  "dataNascimento": "23/12/1999"
}

I tried to receive in my controller and play for a Strategy and that Strategy model my data and validate the information according to some sending standard identifier that the customer inform.

Example 1: Identifier A,Name,Date of Birth Example 2 : First name, Last name, Date of birth , Height.

Thus, I would take this identifier and know which model to use to save to my database in the right way, validate the information correctly in my validators and insert in my document with the correct and non-null fields.

However, I do not know if this is the best way or if there is another way. I don’t know if Strategy applies in this context, I also thought about Abstract Factory but I don’t think it applies.

There is another simpler way?

I can already save the receipt whatever it is within a Generic model, which has all fields and types, but I believe it is not the best practice because if a certain type of payload does not fill some fields, these fields have null values and the most complex validation, in addition to each addition of a new behavior, need to add more fields in this Generic model.

1 answer

0


I think the simplest is to have a common interface for the N models you have, and then you use a Factory to convert the data you received to this interface.

interface Monstro {
  validar(): boolean;
}

class Bruxa implements Monstro {
  constructor(
    public nivelFeiura: number,
    public poder: number,
    public tipoVassoura: string
  ) {}

  validar() {
    const FEIURA_MINIMA = 665;

    return (
      this.nivelFeiura > FEIURA_MINIMA &&
      this.tipoVassoura !== 'Vassoura Normal'
    );
  }
}

class Goblin implements Monstro {
  constructor(public arma: string, public alturaEmCm: number) {}

  validar() {
    return this.armaValida() && this.alturaValida();
  }

  private armaValida() {
    const armasValidas = [
      'Faca',
      'Adaga',
      'Peixeira',
      'Canivete',
      'Caco de Vidro',
    ];
    return armasValidas.includes(this.arma);
  }

  private alturaValida() {
    return this.alturaEmCm >= 70 && this.alturaEmCm <= 120;
  }
}

class MonstroFactory {
  criarMonstro(payload: Record<string, string | number>): Monstro {
    if ('nivelFeiura' in payload) {
      return new Bruxa(
        Number(payload.nivelFeiura),
        Number(payload.poder),
        String(payload.tipoVassoura)
      );
    }

    if ('arma' in payload) {
      return new Goblin(String(payload.arma), Number(payload.alturaEmCm));
    }

    throw new Error('Monstro desconhecido');
  }
}

With this, you can look at your payload at a higher level of abstraction, following Liskov’s substitution principle. Be it Goblin or Witch, you know it is a monster and you can validate it. Of course, it will be simple to add other monsters later.

Now, so before you go out applying Pattern design and everything, you need to have some discretion. Does your problem really ask for this kind of solution, or is it something simple, where it only differs one or two fields? When in doubt, keep it as simple and straightforward as possible, otherwise you may be bringing unnecessary complexity to your code.

  • It is also worth considering whether this sending of several different models in the same endpoint does not hurt the SRP. That is, if it wouldn’t make sense to have different endpoints for each model. It depends a lot on what you’re implementing.

  • Perfect Allan, in my case and the same functionality that depending on the selected combobox wins new fields or other names. With this I need to receive this information dynamically and model/validate it to save in my bank differently because the fields may have different types or sizes. Now Factory makes more sense with your example than using Strategy. At first I was saving everything in the same way, in a large interface that did not differentiate the receipt of information, with all possible fields. Now I’m trying to model that receipt.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.