4

I'm running into an issue (or what I believe to be one) with Joi validation. I'm trying to assign a value to a non-existent key if it's been passed as part of the request body.

So for example:

parameters: Joi.object().keys({
  keyA: Joi.string().allow('').allow(null).default(null),
  keyB: Joi.object().keys({
    b1: Joi.string(),
    b2: Joi.string(),
    b3: Joi.object().keys({
      b3_1: Joi.string(),
      b3_2: Joi.string(),
      b3_3: Joi.string()
    })
  }).default({}),
  keyC: Joi.object().keys({
    c1: Joi.number(),
    c2: Joi.number(),
    c3: Joi.boolean(),
    c4: Joi.boolean()
  }).default({}),
  keyD: Joi.object().keys({
    d1: Joi.number(),
    d2: Joi.number()
  }).default({}),
  keyE: Joi.object().keys({
    e1: Joi.number()
  }).default({}) 
}).allow(null)

So to be specific if I were to pass in:

{
  keyA: "foo",
  keyD: {
    d1: 21.9,
    d2: 21.1
  },
  keyE: {
    e1: 42
  }
}

I would get this in return

{
  keyA: "foo",
  keyB: {},
  keyC: {},
  keyD: {
    d1: 21.9,
    d2: 21.1
  },
  keyE: {
    e1: 42
  }
}

With :eyes: on the empty objects. What am I missing with the Joi.default() method? Am I overextending what Joi is meant for?

bneigher
  • 818
  • 4
  • 13
  • 24

2 Answers2

3

I'll start by pointing out that the schema in your question isn't valid JavaScript, you've closed a few too many brackets before declaring the rule for keyC. I'll assume this is simply a formatting error with the question and your actual schema is currently valid.

Secondly, there's nothing wrong with how you've declared your defaults.. it works just fine. I'll assume it's the way you're validating the schema which is the problem.

Try running this. I've mimicked the validation method in the docs for default().

const schema = Joi.object().keys({
    keyA: Joi.string().allow('').allow(null).default(null),
    keyB: Joi.object().keys({
        b1: Joi.string(),
        b2: Joi.string(),
        b3: Joi.object().keys({
            b3_1: Joi.string(),
            b3_2: Joi.string(),
            b3_3: Joi.string()
        })
    }).default({}),
    keyC: Joi.object().keys({
        c1: Joi.number(),
        c2: Joi.number(),
        c3: Joi.boolean(),
        c4: Joi.boolean()
    }).default({}),
    keyD: Joi.object().keys({
        d1: Joi.number(),
        d2: Joi.number()
    }).default({}),
    keyE: Joi.object().keys({
        e1: Joi.number()
    }).default({})
}).allow(null);

Joi.validate({
    keyA: "foo",
    keyD: {
        d1: 21.9,
        d2: 21.1
    },
    keyE: {
        e1: 42
    }
}, schema, (err, value) =>
{
    if (err)
        throw err;

    console.log(value);
});

I get this in the console:

{
    keyA :'foo',
    keyD: {
        d1: 21.9,
        d2: 21.1
    },
    keyE: {
        e1: 42
    },
    keyB: {},
    keyC: {}
}

The keys are unlikely to look ordered like your expected output, but that shouldn't matter as object keys are not ordered anyway.

Community
  • 1
  • 1
Ankh
  • 5,478
  • 3
  • 36
  • 40
  • Yes you are correct - the problem ended up being in an outer library that was stripping empty objects. – bneigher Mar 30 '17 at 19:10
0

You can set the default values, you should try this:

parameters: Joi.object().keys({
  keyA: Joi.string().allow(null).default(null),
  keyB: Joi.object().keys({
    b1: Joi.string().default("abc"),
      b2: Joi.string().default("abc"),
      b3: Joi.object().keys({
        b3_1: Joi.string().default("abc"),
        b3_2: Joi.string().default("abc"),
        b3_3: Joi.string().default("abc")
      })
    })
  }).default({}),
  keyC: Joi.object().keys({
    c1: Joi.number().default(0),
    c2: Joi.number().default(0),
    c3: Joi.boolean().default(0),
    c4: Joi.boolean().default(0)
  }).default({}),
  keyD: Joi.object().keys({
    d1: Joi.number().default(0),
    d2: Joi.number().default(0)
  }).default({}),
  keyE: Joi.object().keys({
    e1: Joi.number().default(0)
  }).default({}) 
}).allow(null)
Shubham Verma
  • 8,783
  • 6
  • 58
  • 79
  • Thanks for getting back! The goal is to set the default values of the objects as empty objects. I'm not concerned about the values of the object's keys -- they are just there to show my example – bneigher Mar 30 '17 at 06:57
  • It seems as if Joi.object().default() is not respected – bneigher Mar 30 '17 at 06:57