Extract the necessary fields from the JSON Schema

I am in search of a solution to extract the required fields from a JSON Schema and Data combination.

Currently, we are utilizing AJV for getting error messages in our forms using JSON Schema, and it has been performing really well.

I am looking for a method to retrieve all the required fields (even if already filled) so that I can label those fields with * as "required". The required fields may vary depending on the schema and data combinations.

I also attempted to extract the required fields using tv4, but without success.

Your assistance would be greatly appreciated.


Here is an example of such a schema:

{
  "type": "object",
  "required": [
    "checkbox"
  ],
  "properties": {
    "checkbox": {
      "type": "boolean"
    },
    "textbox": {
      "type": "string"
    }
  },
  "oneOf": [
    {
      "required": [
        "textbox"
      ],
      "properties": {
        "checkbox": {
          "enum": [
            true
          ]
        }
      }
    },
    {
      "properties": {
        "checkbox": {
          "enum": [
            false
          ]
        }
      }
    }
  ],
  "additionalProperties": false
}

Answer №1

After reviewing your inquiry, the most straightforward approach to achieve your desired outcome would be:

  1. Retrieve the Json data when the page loads,
  2. Go through the json data to eliminate valid values (refer to example 1),
  3. Invoke tv4.validateMultiple(data, schema),
  4. Inspect the result object and retrieve the necessary fields (refer to example 2).

example 1

for(let prop in data) {
    if(data.hasOwnProperty(prop)) {
        //assign a null value, -1, or any other universally undesirable value
        data[prop].value = null;
    }
}

example 2

let result = tv4.validateMultiple(data, schema);
let required = result.errors;

Answer №2

The issue was resolved through the following steps:

  1. We decided to fork tv4 (renamed as tv4 - for ease of editing) by visiting the link below:

    https://github.com/mikila85/tv4

    We then generated an array of "Requireds".

  2. Next, we proceeded to iterate through each required field, resetting its data and forwarding the data+schema to AJV for validation (opted for AJV over tv4 due to quicker parsing).

This approach allowed us to identify which specific required fields were necessary for the provided data.

Below are the functional implementations we crafted (though not the most polished, they serve their purpose well):

function getAllRequiredFields() {
    var allRequiredFields = tv4.validateMultiple($scope.formModel, $scope.formSchema).requireds;
    allRequiredFields = allRequiredFields.filter(function onlyUnique(value, index, self) {
        return self.indexOf(value) === index;
    });

    return allRequiredFields;
}

function getRequiredFields() {
    var t0 = performance.now();

    // This function should be invoked on every model change for optimal performance as it utilizes tv4's data+schema optimization.
    var allRequiredFields = getAllRequiredFields();
    angular.forEach(allRequiredFields, function (requiredPath) {
        var modelWithDeletedRequiredProperty = angular.copy($scope.formModel);

        deleteValue(modelWithDeletedRequiredProperty, requiredPath);
        if (!validateForm(modelWithDeletedRequiredProperty)) {

            var requiredError = getErrorObjectsArray(validateForm.errors).find(function (error) {
                return error.path === requiredPath;
            });

            if (requiredError) {
                localValidation[requiredError.inputName] = localValidation[requiredError.inputName] || {};
                localValidation[requiredError.inputName].isRequired = true;
                requiredFieldsPath.push(requiredError.inputName);
            }
        }
    });

    var t1 = performance.now();
    console.log("form checking took " + (t1 - t0) + " milliseconds.");
}

Answer №3

This particular function is designed to retrieve schema indices in a recursive manner, offering the possibility for customization.

   // https://github.com/pubkey/rxdb/blob/master/src/rx-schema.js
 export function obtainIndices(schemaJSON, previousPath = '') {
        let schemaIndexes = [];
        Object.entries(schemaJSON).forEach(entry => {
            const key = entry[0];
            const obj = entry[1];
            const path = key === 'properties' ? previousPath : util.trimDots(previousPath + '.' + key);

            if (obj.index)
                indexes.push([path]);

            if (typeof obj === 'object' && !Array.isArray(obj)) {
                const additionalIndices = getIndexes(obj, path);
                schemaIndexes = schemaIndexes.concat(additionalIndices);
            }
        });

        if (previousPath === '') {
            const additionalCompoundIndices = schemaJSON.compoundIndexes || [];
            schemaIndexes = schemaIndexes.concat(additionalCompoundIndices);
        }

        schemaIndexes = schemaIndexes
            .filter((element, position, array) => array.indexOf(element) === position); // unique;
        return schemaIndexes;
    }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing AngularJS's $http.get to fetch video IDs and then combining them with the /embed endpoint through the ng

Currently, I am utilizing $http.get to retrieve a list of videos from YouTube using the API endpoint 'MY_API_KEY'. The goal is to construct a link with the video ID in the format: "{{videoID}}". However, extracting the videoID proves to be chall ...

Inquiries regarding scopes, node.js, and express

I struggle with understanding scopes and similar concepts in various programming languages. Currently, I am working on an express application where I take user input, query an arbitrary API, and display the results in the console. To interact with the REST ...

Take action once the Promise outside of the then block has been successfully completed

Presented below is the code snippet: function getPromise():Promise<any> { let p = new Promise<any>((resolve, reject) => { //some logical resolve(data); }); p.finally(()=>{ //I want do something when ou ...

How can one efficiently update numerous data properties in a Vue.js application?

My information is as follows: data() { return { monday_start: '', monday_end: '', tuesday_start: '', tuesday_end: '', wednesday_start: '', ...

Obtaining IDs of Divs that have been Dragged into a Drop Zone upon Clicking a Button using JavaScript

I'm currently working on a solution to extract the ids of dragged divs once they have been placed in the drop zone. Each drag component is assigned an id ranging from drag1 through drag8, while the drop zone is labeled as div drop zone. Since there a ...

Guide on creating multiple instances of vue-multiselect with a simple button click

I am trying to implement a vue-multiselect dropdown with the addition of a new dropdown upon clicking an "add more" button. However, I am currently unsure of the best approach to achieve this. Problem/Question: When adding 2 dropdowns, if the same option ...

What is the best way to convert a Java 8 LocalDateTime property to a JavaScript-style Date String when using JAX-RS?

I implemented a RESTful web service using JAX-RS method annotations: @GET @Path("/test") @Produces(MediaType.APPLICATION_JSON) public MyThing test() { MyThing myObject = new MyThing(LocalDateTime.now()); return myObject; } Everything is working s ...

Error occurred in the middle of processing, preventing the headers from being set

I created a custom authentication middleware, but encountered an error. I'm puzzled about what's going wrong because I expected the next() function to resolve the issue? app.use(function(req, res, next){ if(req.user){ res.local ...

ngTagsInput retrieves and processes information from the database

Before sending data to the database using ngTagsInput, I perform the following action: angular.toJson($scope.tags); Upon retrieving the data, my scope displays something similar to this: [{"text":"abc"},{"text":"cba"},{"text":"tag"}] How can I display ...

Angular update row and save data to an array

When comparing the data of an edited row with the row just below it, I encounter a specific scenario. In a table containing 5 rows, as I edit records from top to bottom using the provided code snippet, I am able to store the values in an array. The most re ...

The operation of my NodeJS application suddenly halts

In my project, I have a Server.js file that I run from the command line using: node server Within the Server.js file, a new instance of class A is created Class A then creates instances of both class B (web socket) and class C (REST API) If the web socket ...

Retrieve data from a website's API endpoint using JSON format and display it on a

I came across a URL that displays [{"outlet_group_id": "29","outlet_group_name": "Parco","outlet_group_code": "0000010"}] and I have the following code snippet <script> $(document).ready(function() { $.getJSON('http://sampl.elinkurl.com/ ...

Extract information from a JSON file and import it into an Angular TypeScript file

How can I retrieve data from a JSON file and use it in an Angular typescript file for displaying on web pages? this.http.get<any>('http://localhost:81/CO226/project/loginResult.json').subscribe((res: Response)=>{ }); Here ...

C# Deserialize JSON Array

Attempting to utilize JSON to retrieve weather data from the Climatempo API, I encountered the following error due to one of the items being an array. I attempted to make the following change: public static ClimaTempo15 FromJson(string json) => JsonCon ...

Issue encountered with Fabric js: Unable to apply pattern fill to a group of rectangles

Greetings, I am in need of some assistance with a coding issue. I have a for loop that generates and adds multiple rectangles to a fabric js canvas. To set a texture for each rectangle, I am using the following code snippet. var rect = new fabric.Rect( ...

Experiencing an excessive number of re-renders can be a common issue in React as it has limitations set in place to prevent infinite loops. This

I have integrated React context to access the login function and error from the context provider file for logging into the firebase database. I am trying to display any thrown errors in the app during the login process. However, I encountered an issue whe ...

Issue with modal rendering in Bootstrap4 when the body is zoomed in

I am encountering an issue with a Bootstrap html page where the body is zoomed in at 90%. The Bootstrap modal is displaying extra spaces on the right and bottom. To showcase this problem, I have created a simple html page with the modal and body set to 90% ...

What is the best way to save the values of all the input fields in a datatable, excluding any fields that are empty?

$('form').on('submit', function(e){ var form = this; // Encoding a set of form elements from all pages as an array of names and values var params = table.$('input').serializeArray(); // Iterating over all form ...

Is it possible to extend the String prototype with the forEach method as found in the Array prototype?

It is common knowledge that there is a .forEach() method for arrays in JavaScript, but unfortunately Strings do not have that method integrated. So, the question arises: is it problematic to use the following code snippet: String.prototype.forEach = Array ...

Execute a function for each template or controller when the page loads

I recently developed a function for my application that verifies the users' information. I implemented this in my authentication controller within the $rootScope. However, I am facing an issue where I need to manually invoke this function in all of m ...