Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uniqueItemProperties on non-required keys fails with multiple items with undefined keys #115

Open
JamesJansson opened this issue Feb 13, 2020 · 10 comments
Labels

Comments

@JamesJansson
Copy link

Using uniqueItemProperties: ['id'] where id is not required should (in my opinion, maybe it should be a separate function) allow multiple elements that have undefined id values. e.g.

[{id: 'a', val: 1}] - should pass

[{id: 'a', val: 1}, {id: 'b', val: 2}] - should pass

[{id: 'a', val: 1}, {id: 'a', val: 2}] - should fail

[{id: 'a', val: 1}, {val: 2}] - should pass

[{val: 1}, {val: 2}] - should pass (but doesn't under current uniqueItemProperties)

I have created a runkit here (code below as well):
https://runkit.com/jamesjansson/ajv-uniqueitemproperties-on-non-required-keys

const Ajv = require("ajv");
const ajvKeywords = require("ajv-keywords")

function validateJson(json, schema) {
  const ajv = new Ajv({
    verbose: true,
    allErrors: true,
    useDefaults: true,
    format: 'full',
    $data: true,
  });
  ajvKeywords(ajv);
  const validate = ajv.compile(schema);
  const isValid = validate(json);
  return {
    isValid,
    errors: validate.errors,
  };
}

const jsonSchema = {
  type: 'array',
  uniqueItemProperties: ['id'],
  items: {
    type: 'object',
    properties: {
      id: { type: 'string', format: 'uuid' },
      otherData: { type: 'string' },
    },
    required: ['otherData'],
    additionalProperties: false,
  },
};

console.log('it should succeed with a single item with no id')
const testData = [
    {
      otherData: 'stuff',
    },
];
const validation1 = validateJson(testData, jsonSchema);
console.log(validation1)

console.log('it should succeed with a two items with no id')
const testData2 = [
    {
        otherData: 'stuff0',
    },
    {
        otherData: 'stuff1',
    },
];
const validation2 = validateJson(testData2, jsonSchema);
console.log(validation2)
@Sumbersss
Copy link

I join you on your comment, uniqueItemProperties should not behave like a required, only check if item is uniq, if not present it should pass

@epoberezkin
Copy link
Member

What is the use case for this behaviour?

@Sumbersss
Copy link

Sumbersss commented Apr 10, 2020

I have the same issue :
I have an array of objects which contain some properties required and some properties that must be uniq.
If an uniq property isn't present in the object the validation fails. It shouldn't, uniq property is different than required property.

@epoberezkin
Copy link
Member

As I wrote, before changing or extending the current behaviour, it would help to understand what is the real life data scenario when such data model is needed. This feature is created to validate the list of objects with unique IDs, such as database IDs, for example - they would be required properties.
What is the use case for having unique non-required properties in the list of objects?

Also, the analogous keyword "uniqueItems" would not validate non-unique "missing" items (missing items in JSON would be nulls - no other way you can represent it in JSON - and the validation would fail). So following this logic, the current behaviour makes more sense - you can only have one object where property that has to be unique is missing.

In any case you can define a slightly modified version of these keyword in your code using this implementation as a starting point.

@Sumbersss
Copy link

I get what you mean, indeed it makes sense if you compare this behaviour with database validation.

@JamesJansson
Copy link
Author

This functionality would be useful in our system. We never let the user create ids, but we may need ways for our FE to determine exactly what item has been updated. As such our API allows an optional tempId field that allows the FE to keep track of which item is being updated and referenced before an entry and its ID is created in the BE.

@mebibou
Copy link

mebibou commented Jul 15, 2021

I'm working on a project where we use JSON files for storing our data. Some data contains arrays where we need to make sure the items are unique based on some keys, but those keys are not always specified, in which case only the present keys should be used to validate the item, which is quite logic to me. At the very least there should be a uniqueRequiredItemProperties along that should do what the current one does, shouldn't it?

@nunico
Copy link

nunico commented Oct 8, 2021

We also have use cases where a user-defined object can have optional properties which need to be unique.

Best example: User-Directory sync. A client wants to onboard their users to a service and sync those user-data. Some clients might want to provide an external reference with their data to provide a mapping.

Also, the example in the documentation won't work either.

@o-nix
Copy link

o-nix commented Sep 20, 2023

My use-case: workflow steps. They might be "just" code definitions on their own, but sometimes they might have IDs, which must be unique, this way you can refer to a previous step in one of the next steps.
TL;DR: the property itself is not required, but must be unique when present.

@sapzs
Copy link

sapzs commented Apr 2, 2024

Another usecase: We validate loadbalancer rules, which optionally include a priority. IF the priority is given, it must be unique across the LB. It is optional, so when no value is given, our backend generates priorities based on the rule order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

7 participants