glideapps / quicktype

Generate types and converters from JSON, Schema, and GraphQL
https://app.quicktype.io
Apache License 2.0
11.79k stars 1.04k forks source link

[BUG]: Minimum integer values are not handled correctly when generating C++ code. #2627

Open beat-schaer opened 1 week ago

beat-schaer commented 1 week ago

Issue Type

This is an issue with quicktype output in C++. Maybe the effect also occurs in other output languages.

Context (Environment, Version, Language)

Input Format: JSON schema, draft-07 Output Language: C++

app.quicktype.io Version: current

Description

I defined integer properties and expected, that they are checked properly within the generated C++ class. The generated ClassMemberConstraint class allows checking of minimum values for integer. However, it seems that they are not used!

Input Data

This is a little JSON schema showcasing the problem:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$ref": "#/definitions/TestObject",
    "definitions": {
        "TestObject": {
            "type": "object",
            "properties": {
                "integer_with_minimum": {
                    "type": "integer",
                    "minimum": 0
                },
                "integer_with_maximum": {
                    "type": "integer",
                    "maximum": 999
                },
                "integer_with_both": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 999
                }
            },
            "required": [ "integer_with_minimum", "integer_with_maximum", "integer_with_both" ]
        }
    }
}

Expected Behaviour / Output

This is what I expected to be generated. Note the content of the first 2 parameters of each _constraint constructor call.

#pragma once

#include "json.hpp"
#include "helper.hpp"

namespace data {
    using nlohmann::json;

    class TestObject {
        public:
        TestObject() :
            integer_with_both_constraint(0, 999, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt),
            integer_with_maximum_constraint(std::nullopt, 999, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt),
            integer_with_minimum_constraint(0, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt)
        {}
        virtual ~TestObject() = default;

        private:
        int64_t integer_with_both;
        ClassMemberConstraints integer_with_both_constraint;
        int64_t integer_with_maximum;
        ClassMemberConstraints integer_with_maximum_constraint;
        int64_t integer_with_minimum;
        ClassMemberConstraints integer_with_minimum_constraint;

        public:
        const int64_t & get_integer_with_both() const { return integer_with_both; }
        int64_t & get_mutable_integer_with_both() { return integer_with_both; }
        void set_integer_with_both(const int64_t & value) { CheckConstraint("integer_with_both", integer_with_both_constraint, value); this->integer_with_both = value; }

        const int64_t & get_integer_with_maximum() const { return integer_with_maximum; }
        int64_t & get_mutable_integer_with_maximum() { return integer_with_maximum; }
        void set_integer_with_maximum(const int64_t & value) { CheckConstraint("integer_with_maximum", integer_with_maximum_constraint, value); this->integer_with_maximum = value; }

        const int64_t & get_integer_with_minimum() const { return integer_with_minimum; }
        int64_t & get_mutable_integer_with_minimum() { return integer_with_minimum; }
        void set_integer_with_minimum(const int64_t & value) { CheckConstraint("integer_with_minimum", integer_with_minimum_constraint, value); this->integer_with_minimum = value; }
    };
}

Current Behaviour / Output

This is what I get: The maximum is correctly placed in the code. However the minimum is always absent!

#pragma once

#include "json.hpp"
#include "helper.hpp"

namespace data {
    using nlohmann::json;

    class TestObject {
        public:
        TestObject() :
            integer_with_both_constraint(std::nullopt, 999, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt),
            integer_with_maximum_constraint(std::nullopt, 999, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt),
            integer_with_minimum_constraint(std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt)
        {}
        virtual ~TestObject() = default;

        private:
        int64_t integer_with_both;
        ClassMemberConstraints integer_with_both_constraint;
        int64_t integer_with_maximum;
        ClassMemberConstraints integer_with_maximum_constraint;
        int64_t integer_with_minimum;
        ClassMemberConstraints integer_with_minimum_constraint;

        public:
        const int64_t & get_integer_with_both() const { return integer_with_both; }
        int64_t & get_mutable_integer_with_both() { return integer_with_both; }
        void set_integer_with_both(const int64_t & value) { CheckConstraint("integer_with_both", integer_with_both_constraint, value); this->integer_with_both = value; }

        const int64_t & get_integer_with_maximum() const { return integer_with_maximum; }
        int64_t & get_mutable_integer_with_maximum() { return integer_with_maximum; }
        void set_integer_with_maximum(const int64_t & value) { CheckConstraint("integer_with_maximum", integer_with_maximum_constraint, value); this->integer_with_maximum = value; }

        const int64_t & get_integer_with_minimum() const { return integer_with_minimum; }
        int64_t & get_mutable_integer_with_minimum() { return integer_with_minimum; }
        void set_integer_with_minimum(const int64_t & value) { CheckConstraint("integer_with_minimum", integer_with_minimum_constraint, value); this->integer_with_minimum = value; }
    };
}

Steps to Reproduce

  1. Insert the mentioned input at app.quicktype.io
  2. Choose C++ as the language
  3. You should see now the generated code containing the mentioned snippet.

Possible Solution

Correctly insert the constraint value in the call of the constraint constructor.