Skip to content

Building Payload Validation

This document describes the validation rules applied to the Building GeoJSON payloads in the system. The validation is performed in two layers:

  1. JSON Schema Validation: Structural and field-level constraints.
  2. Runtime Validation: Business rules and contextual consistency enforced by application logic.
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://geojson.org/schema/Building.json",
  "title": "GeoJSON Building",
  "type": "object",
  "required": [
    "type",
    "features"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "FeatureCollection"
      ]
    },
    "features": {
      "type": "array",
      "items": {
        "title": "GeoJSON Building",
        "type": "object",
        "required": [
          "type",
          "properties",
          "geometry"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "Feature"
            ]
          },
          "id": {
            "type": "number"
          },
          "properties": {
            "type": "object",
            "required": [
              "fid",
              "typeCode",
              "name",
              "sid"
            ],
            "properties": {
              "fid": {
                "type": "string",
                "maxLength": 36,
                "minLength": 1
              },
              "name": {
                "type": "string",
                "maxLength": 100,
                "minLength": 0
              },
              "typeCode": {
                "type": "string",
                "enum": [
                  "building-outline"
                ]
              },
              "sid": {
                "type": "string"
              }
            }
          },
          "geometry": {
            "oneOf": [
              {
                "title": "GeoJSON Polygon",
                "type": "object",
                "required": ["type", "coordinates"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["Polygon"]
                  },
                  "coordinates": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "array",
                      "minItems": 4,
                      "items": {
                        "type": "array",
                        "minItems": 2,
                        "items": [
                          {
                            "type": "number",
                            "multipleOf": 0.00000001,
                            "exclusiveMinimum": -180,
                            "exclusiveMaximum": 180
                          },
                          {
                            "type": "number",
                            "multipleOf": 0.00000001,
                            "exclusiveMinimum": -90,
                            "exclusiveMaximum": 90
                          }
                        ]
                      }
                    }
                  },
                  "bbox": {
                    "type": "array",
                    "minItems": 4,
                    "items": {
                      "type": "number"
                    }
                  }
                }
              },
              {
                "title": "GeoJSON MultiPolygon",
                "type": "object",
                "required": ["type", "coordinates"],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["MultiPolygon"]
                  },
                  "coordinates": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "array",
                        "minItems": 4,
                        "items": {
                          "type": "array",
                          "minItems": 2,
                          "items": [
                            {
                              "type": "number",
                              "multipleOf": 0.00000001,
                              "exclusiveMinimum": -180,
                              "exclusiveMaximum": 180
                            },
                            {
                              "type": "number",
                              "multipleOf": 0.00000001,
                              "exclusiveMinimum": -90,
                              "exclusiveMaximum": 90
                            }
                          ]
                        }
                      }
                    }
                  },
                  "bbox": {
                    "type": "array",
                    "minItems": 4,
                    "items": {
                      "type": "number"
                    }
                  }
                }
              }
            ]
          },
          "bbox": {
            "type": "array",
            "minItems": 4,
            "items": {
              "type": "number"
            }
          }
        }
      }
    },
    "bbox": {
      "type": "array",
      "minItems": 4,
      "items": {
        "type": "number"
      }
    }
  }
}

1. JSON Schema Validation

The JSON payload must follow the FeatureCollection pattern and contain an array of Feature items, each representing a building.

🔸 Root Object

  • type: "FeatureCollection" (required)
  • features: array of GeoJSON Feature objects (required)
  • bbox: optional array with at least 4 numbers

🔸 features[].type

  • Must be "Feature" (required)

🔸 features[].id

  • Optional numeric identifier

🔸 features[].properties

  • Must include the following fields (required):
    • fid: string (length: 1–36)
    • name: string (max length: 100)
    • typeCode: must be "building-outline"
    • sid: string

🔸 features[].geometry

  • Must be either a GeoJSON Polygon or MultiPolygon
  • Coordinates must:

    • Conform to valid GeoJSON structure
    • Include at least 4 coordinate points for each ring
    • Use valid latitude (-90 < lat < 90) and longitude (-180 < lon < 180), with high precision
  • Optional bbox array with at least 4 numbers

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://geojson.org/schema/Building.json",
  "title": "GeoJSON Building",
  "type": "object",
  "required": [
    "type",
    "properties",
    "geometry"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "Feature"
      ]
    },
    "id": {
      "type": "number"
    },
    "properties": {
      "type": "object",
      "required": [
        "fid",
        "typeCode",
        "name",
        "sid"
      ],
      "properties": {
        "fid": {
          "type": "string",
          "maxLength": 36,
          "minLength": 1
        },
        "name": {
          "type": "string",
          "maxLength": 100,
          "minLength": 0
        },
        "typeCode": {
          "type": "string",
          "enum": [
            "building-outline"
          ]
        },
        "sid": {
          "type": "string"
        }
      }
    },
    "geometry": {
      "oneOf": [
        {
          "title": "GeoJSON Polygon",
          "type": "object",
          "required": ["type", "coordinates"],
          "properties": {
            "type": {
              "type": "string",
              "enum": ["Polygon"]
            },
            "coordinates": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "array",
                "minItems": 4,
                "items": {
                  "type": "array",
                  "minItems": 2,
                  "items": [
                    {
                      "type": "number",
                      "multipleOf": 0.00000001,
                      "exclusiveMinimum": -180,
                      "exclusiveMaximum": 180
                    },
                    {
                      "type": "number",
                      "multipleOf": 0.00000001,
                      "exclusiveMinimum": -90,
                      "exclusiveMaximum": 90
                    }
                  ]
                }
              }
            },
            "bbox": {
              "type": "array",
              "minItems": 4,
              "items": {
                "type": "number"
              }
            }
          }
        },
        {
          "title": "GeoJSON MultiPolygon",
          "type": "object",
          "required": ["type", "coordinates"],
          "properties": {
            "type": {
              "type": "string",
              "enum": ["MultiPolygon"]
            },
            "coordinates": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "array",
                "items": {
                  "type": "array",
                  "minItems": 4,
                  "items": {
                    "type": "array",
                    "minItems": 2,
                    "items": [
                      {
                        "type": "number",
                        "multipleOf": 0.00000001,
                        "exclusiveMinimum": -180,
                        "exclusiveMaximum": 180
                      },
                      {
                        "type": "number",
                        "multipleOf": 0.00000001,
                        "exclusiveMinimum": -90,
                        "exclusiveMaximum": 90
                      }
                    ]
                  }
                }
              }
            },
            "bbox": {
              "type": "array",
              "minItems": 4,
              "items": {
                "type": "number"
              }
            }
          }
        }
      ]
    },
    "bbox": {
      "type": "array",
      "minItems": 4,
      "items": {
        "type": "number"
      }
    }
  }
}

1. JSON Schema Validation

The incoming payload must conform to the following rules defined in the JSON Schema:

🔸 Root Object

  • type: must be "Feature" (required).
  • id: optional numeric identifier.
  • bbox: optional array with at least 4 numerical values.

🔸 properties Object

  • fid (Feature Identifier):

    • Required
    • String
    • Minimum length: 1
    • Maximum length: 36
  • name:

    • Required
    • String
    • Maximum length: 255
  • typeCode:

    • Required
    • Must be "building-outline"
  • sid (Feature Identifier):

    • Required
    • String
    • Minimum length: 1
    • Maximum length: 36
  • Other fields are allowed unless explicitly forbidden (see Runtime Validation section).

🔸 geometry Object

  • Must be a valid GeoJSON Polygon or MultiPolygon object.
    • Conform to valid GeoJSON structure.
    • Include at least 4 coordinate points for each ring.
    • Have latitude (lat) in range (-90, 90) and longitude (lon) in range (-180, 180), with high precision.

    Coordinates must:

    • Optional bbox field must be an array of at least 4 numbers.

2. Runtime Validations (Application Logic)

The following validations are implemented in application code and cannot be enforced via schema alone:

🔹 1. fid (Feature Identifier)

  • If missing:
    → "fid is required."

  • If present but invalid:
    → "The fid field contains an invalid value."

  • If a buildingIdentifier is specified but does not match the payload's fid:
    → "The requested buildingIdentifier and payload fid information do not match."

  • If no buildingIdentifier is specified and a building with the same fid already exists:
    → "The building with given fid is already exist."

🔹 2. sid (Site Identifier)

  • If missing:
    → "sid is required. fid: '{fid}'"

  • If present but invalid:
    → "The sid field contains an invalid value."

  • If the provided sid does not match the request's siteIdentifier:
    → "The requested siteIdentifier and payload sid do not match. fid: '{fid}'"

🔹 3. name

  • If missing or empty:
    → "The name field cannot be empty."

  • If length exceeds max (e.g., 100):
    → "Building name cannot exceed '100' characters."

🔹 4. eid (External Identifier)

  • If present and empty:
    → "The eid field cannot be empty."

  • If present and already used by another building with a different fid:
    → "Another building exists with the same buildingExternalIdentifier for this client."

🔹 5. buildingType

  • Must be present and non-empty
    → "buildingType is required. fid: '{fid}'"

  • Must be one of the allowed values defined in Constants.AllowedStructureTypes (case-insensitive)
    → "The buildingType is invalid."

🔹 6. Forbidden Properties

The following properties must not appear in the properties object of any feature:

  • "bid"
  • "lvl"

If any of these are found:
→ "The properties 'bid, lvl' are forbidden."

🔹 7. Building Movement Validation

If the building is being moved to another site (i.e., sid in payload is different from request siteIdentifier):

  • The target site must exist
    → "The building could not be moved because the specified sid with '{sid}' could not be found."

  • The building must not already exist in the target site
    → "The building could not be moved because it already exists under the specified sid with '{sid}'."

By combining schema-level validation with rich runtime logic, the system ensures consistent, secure, and meaningful building data ingestion.