Skip to content

Beacons Payload Validation

This document describes the validation rules applied to the Beacons 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/FeatureCollection.json",
  "title": "GeoJSON FeatureCollection",
  "type": "object",
  "required": [
    "type",
    "features"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "FeatureCollection"
      ]
    },
    "features": {
      "type": "array",
      "items": {
        "title": "GeoJSON Feature",
        "type": "object",
        "required": [
          "type",
          "properties",
          "geometry"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "Feature"
            ]
          },
          "id": {
            "oneOf": [
              {
                "type": "number"
              },
              {
                "type": "string"
              }
            ]
          },
          "properties": {
            "type": "object",
            "required": [
              "typeCode"
            ],
            "properties": {
              "typeCode": {
                "type": "string"
              }
            }
          },
          "geometry": {
            "oneOf": [
              {
                "title": "GeoJSON Point",
                "type": "object",
                "required": [
                  "type",
                  "coordinates"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "Point"
                    ]
                  },
                  "coordinates": {
                    "type": "array",
                    "minItems": 2,
                    "items": [
                      {
                        "type": "number",
                        "multipleOf": 1e-8,
                        "exclusiveMinimum": -180,
                        "exclusiveMaximum": 180
                      },
                      {
                        "type": "number",
                        "multipleOf": 1e-8,
                        "exclusiveMinimum": -90,
                        "exclusiveMaximum": 90
                      }
                    ]
                  },
                  "bbox": {
                    "type": "array",
                    "minItems": 4,
                    "items": {
                      "type": "number"
                    }
                  }
                }
              },
              {
                "title": "GeoJSON LineString",
                "type": "object",
                "required": [
                  "type",
                  "coordinates"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "LineString"
                    ]
                  },
                  "coordinates": {
                    "type": "array",
                    "minItems": 2,
                    "items": {
                      "type": "array",
                      "minItems": 2,
                      "items": [
                        {
                          "type": "number",
                          "multipleOf": 1e-8,
                          "exclusiveMinimum": -180,
                          "exclusiveMaximum": 180
                        },
                        {
                          "type": "number",
                          "multipleOf": 1e-8,
                          "exclusiveMinimum": -90,
                          "exclusiveMaximum": 90
                        }
                      ]
                    }
                  },
                  "bbox": {
                    "type": "array",
                    "minItems": 4,
                    "items": {
                      "type": "number"
                    }
                  }
                }
              },
              {
                "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": 1e-8,
                            "exclusiveMinimum": -180,
                            "exclusiveMaximum": 180
                          },
                          {
                            "type": "number",
                            "multipleOf": 1e-8,
                            "exclusiveMinimum": -90,
                            "exclusiveMaximum": 90
                          }
                        ]
                      }
                    }
                  },
                  "bbox": {
                    "type": "array",
                    "minItems": 4,
                    "items": {
                      "type": "number"
                    }
                  }
                }
              },
              {
                "title": "GeoJSON MultiPoint",
                "type": "object",
                "required": [
                  "type",
                  "coordinates"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "MultiPoint"
                    ]
                  },
                  "coordinates": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "array",
                      "minItems": 2,
                      "items": [
                        {
                          "type": "number",
                          "multipleOf": 1e-8,
                          "exclusiveMinimum": -180,
                          "exclusiveMaximum": 180
                        },
                        {
                          "type": "number",
                          "multipleOf": 1e-8,
                          "exclusiveMinimum": -90,
                          "exclusiveMaximum": 90
                        }
                      ]
                    }
                  },
                  "bbox": {
                    "type": "array",
                    "minItems": 4,
                    "items": {
                      "type": "number"
                    }
                  }
                }
              },
              {
                "title": "GeoJSON MultiLineString",
                "type": "object",
                "required": [
                  "type",
                  "coordinates"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "MultiLineString"
                    ]
                  },
                  "coordinates": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "array",
                      "minItems": 2,
                      "items": {
                        "type": "array",
                        "minItems": 2,
                        "items": [
                          {
                            "type": "number",
                            "multipleOf": 1e-8,
                            "exclusiveMinimum": -180,
                            "exclusiveMaximum": 180
                          },
                          {
                            "type": "number",
                            "multipleOf": 1e-8,
                            "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": 1e-8,
                              "exclusiveMinimum": -180,
                              "exclusiveMaximum": 180
                            },
                            {
                              "type": "number",
                              "multipleOf": 1e-8,
                              "exclusiveMinimum": -90,
                              "exclusiveMaximum": 90
                            }
                          ]
                        }
                      }
                    }
                  },
                  "bbox": {
                    "type": "array",
                    "minItems": 4,
                    "items": {
                      "type": "number"
                    }
                  }
                }
              },
              {
                "title": "GeoJSON GeometryCollection",
                "type": "object",
                "required": [
                  "type",
                  "geometries"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "GeometryCollection"
                    ]
                  },
                  "geometries": {
                    "type": "array",
                    "items": {
                      "oneOf": [
                        {
                          "title": "GeoJSON Point",
                          "type": "object",
                          "required": [
                            "type",
                            "coordinates"
                          ],
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "Point"
                              ]
                            },
                            "coordinates": {
                              "type": "array",
                              "minItems": 2,
                              "items": [
                                {
                                  "type": "number",
                                  "multipleOf": 1e-8,
                                  "exclusiveMinimum": -180,
                                  "exclusiveMaximum": 180
                                },
                                {
                                  "type": "number",
                                  "multipleOf": 1e-8,
                                  "exclusiveMinimum": -90,
                                  "exclusiveMaximum": 90
                                }
                              ]
                            },
                            "bbox": {
                              "type": "array",
                              "minItems": 4,
                              "items": {
                                "type": "number"
                              }
                            }
                          }
                        },
                        {
                          "title": "GeoJSON LineString",
                          "type": "object",
                          "required": [
                            "type",
                            "coordinates"
                          ],
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "LineString"
                              ]
                            },
                            "coordinates": {
                              "type": "array",
                              "minItems": 2,
                              "items": {
                                "type": "array",
                                "minItems": 2,
                                "items": [
                                  {
                                    "type": "number",
                                    "multipleOf": 1e-8,
                                    "exclusiveMinimum": -180,
                                    "exclusiveMaximum": 180
                                  },
                                  {
                                    "type": "number",
                                    "multipleOf": 1e-8,
                                    "exclusiveMinimum": -90,
                                    "exclusiveMaximum": 90
                                  }
                                ]
                              }
                            },
                            "bbox": {
                              "type": "array",
                              "minItems": 4,
                              "items": {
                                "type": "number"
                              }
                            }
                          }
                        },
                        {
                          "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": 1e-8,
                                      "exclusiveMinimum": -180,
                                      "exclusiveMaximum": 180
                                    },
                                    {
                                      "type": "number",
                                      "multipleOf": 1e-8,
                                      "exclusiveMinimum": -90,
                                      "exclusiveMaximum": 90
                                    }
                                  ]
                                }
                              }
                            },
                            "bbox": {
                              "type": "array",
                              "minItems": 4,
                              "items": {
                                "type": "number"
                              }
                            }
                          }
                        },
                        {
                          "title": "GeoJSON MultiPoint",
                          "type": "object",
                          "required": [
                            "type",
                            "coordinates"
                          ],
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "MultiPoint"
                              ]
                            },
                            "coordinates": {
                              "type": "array",
                              "minItems": 1,
                              "items": {
                                "type": "array",
                                "minItems": 2,
                                "items": [
                                  {
                                    "type": "number",
                                    "multipleOf": 1e-8,
                                    "exclusiveMinimum": -180,
                                    "exclusiveMaximum": 180
                                  },
                                  {
                                    "type": "number",
                                    "multipleOf": 1e-8,
                                    "exclusiveMinimum": -90,
                                    "exclusiveMaximum": 90
                                  }
                                ]
                              }
                            },
                            "bbox": {
                              "type": "array",
                              "minItems": 4,
                              "items": {
                                "type": "number"
                              }
                            }
                          }
                        },
                        {
                          "title": "GeoJSON MultiLineString",
                          "type": "object",
                          "required": [
                            "type",
                            "coordinates"
                          ],
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "MultiLineString"
                              ]
                            },
                            "coordinates": {
                              "type": "array",
                              "minItems": 1,
                              "items": {
                                "type": "array",
                                "minItems": 2,
                                "items": {
                                  "type": "array",
                                  "minItems": 2,
                                  "items": [
                                    {
                                      "type": "number",
                                      "multipleOf": 1e-8,
                                      "exclusiveMinimum": -180,
                                      "exclusiveMaximum": 180
                                    },
                                    {
                                      "type": "number",
                                      "multipleOf": 1e-8,
                                      "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": 1e-8,
                                        "exclusiveMinimum": -180,
                                        "exclusiveMaximum": 180
                                      },
                                      {
                                        "type": "number",
                                        "multipleOf": 1e-8,
                                        "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"
            }
          }
        }
      }
    },
    "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 feature.

🔸 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)
    • typeCode: must be "ibeacon"
    • sid: string (length: 1–36)
    • bid: string (length: 1–36)
    • lvl: integer

🔸 features[].geometry

  • The geometry must be one of the following valid GeoJSON geometry types, each with specific constraints:
    • Point (Array of 2 numbers: [lon, lat])
    • LineString (Array of ≥2 coordinate pairs [ [lon, lat], ... ])
    • Polygon (Array of linear rings (≥1); each ring array has ≥4 coordinate pairs)
    • MultiPoint (Array of ≥1 coordinate pairs)
    • MultiLineString (Array of LineString arrays; each has ≥2 coordinate pairs)
    • MultiPolygon (Array of Polygon arrays; each polygon contains linear rings with ≥4 coordinate pairs)
    • GeometryCollection (Must have geometries array containing any valid geometries from above)
  • Coordinates must:

    • Conform to valid GeoJSON structure
    • 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/Feature.json",
  "title": "GeoJSON Feature",
  "type": "object",
  "required": [
    "type",
    "properties",
    "geometry"
  ],
  "properties": {
    "type": {
      "type": "string",
      "enum": [
        "Feature"
      ]
    },
    "id": {
      "oneOf": [
        {
          "type": "number"
        },
        {
          "type": "string"
        }
      ]
    },
    "properties": {
      "type": "object",
      "required": [
        "typeCode"
      ],
      "properties": {
        "typeCode": {
          "type": "string"
        }
      }
    },
    "geometry": {
      "oneOf": [
        {
          "title": "GeoJSON Point",
          "type": "object",
          "required": [
            "type",
            "coordinates"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "Point"
              ]
            },
            "coordinates": {
              "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 LineString",
          "type": "object",
          "required": [
            "type",
            "coordinates"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "LineString"
              ]
            },
            "coordinates": {
              "type": "array",
              "minItems": 2,
              "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 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 MultiPoint",
          "type": "object",
          "required": [
            "type",
            "coordinates"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "MultiPoint"
              ]
            },
            "coordinates": {
              "type": "array",
              "minItems": 1,
              "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 MultiLineString",
          "type": "object",
          "required": [
            "type",
            "coordinates"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "MultiLineString"
              ]
            },
            "coordinates": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "array",
                "minItems": 2,
                "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"
              }
            }
          }
        },
        {
          "title": "GeoJSON GeometryCollection",
          "type": "object",
          "required": [
            "type",
            "geometries"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "GeometryCollection"
              ]
            },
            "geometries": {
              "type": "array",
              "items": {
                "oneOf": [
                  {
                    "title": "GeoJSON Point",
                    "type": "object",
                    "required": [
                      "type",
                      "coordinates"
                    ],
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "Point"
                        ]
                      },
                      "coordinates": {
                        "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 LineString",
                    "type": "object",
                    "required": [
                      "type",
                      "coordinates"
                    ],
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "LineString"
                        ]
                      },
                      "coordinates": {
                        "type": "array",
                        "minItems": 2,
                        "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 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 MultiPoint",
                    "type": "object",
                    "required": [
                      "type",
                      "coordinates"
                    ],
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "MultiPoint"
                        ]
                      },
                      "coordinates": {
                        "type": "array",
                        "minItems": 1,
                        "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 MultiLineString",
                    "type": "object",
                    "required": [
                      "type",
                      "coordinates"
                    ],
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "MultiLineString"
                        ]
                      },
                      "coordinates": {
                        "type": "array",
                        "minItems": 1,
                        "items": {
                          "type": "array",
                          "minItems": 2,
                          "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 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
  • typeCode:

    • Required
    • Must be "ibeacon"
  • Other fields are allowed unless explicitly forbidden (see Runtime Validation section).

🔸 geometry Object

  • The geometry must be one of the following valid GeoJSON geometry types, each with specific constraints:
    • Point (Array of 2 numbers: [lon, lat])
    • LineString (Array of ≥2 coordinate pairs [ [lon, lat], ... ])
    • Polygon (Array of linear rings (≥1); each ring array has ≥4 coordinate pairs)
    • MultiPoint (Array of ≥1 coordinate pairs)
    • MultiLineString (Array of LineString arrays; each has ≥2 coordinate pairs)
    • MultiPolygon (Array of Polygon arrays; each polygon contains linear rings with ≥4 coordinate pairs)
    • GeometryCollection (Must have geometries array containing any valid geometries from above)
  • Coordinates must:

    • Conform to valid GeoJSON structure
    • Latitude (-90 < lat < 90) and longitude (-180 < lon < 180) with high precision
  • Optional bbox array with at least 4 numbers


2. Runtime Validations (Application Logic)

These validations are implemented in application code and cannot be enforced via JSON Schema alone:

🔹 1. fid (Feature Identifier)

  • If missing:
    → "fid is required."

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

  • If a featureIdentifier is provided but does not match payload fid:
    → "The requested featureIdentifier and payload fid information do not match."

  • If no featureIdentifier provided and feature with same fid exists:
    → "The feature with given fid already exists."

🔹 2. sid (Site Identifier)

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

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

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

🔹 3. bid (Building Identifier)

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

  • If invalid:
    → "The bid field contains an invalid value."

  • If bid does not match request's buildingIdentifier:
    → "The requested buildingIdentifier and payload bid do not match. fid: '{fid}'"

🔹 4. lvl (Level Identifier)

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

  • If invalid:
    → "The lvl field contains an invalid value."

  • If lvl does not match request's levelIndex:
    → "The lvl field contains an invalid value. fid: '{fid}'"

🔹 5. typeCode Existence Check

  • If typeCode is invalid:
    → "The requested typeCode is not valid. fid : '{fid}'."

🔹 6. UUID

  • Required: Yes
  • Conditions:

    → Must not be null or empty

  • Error Message:

    → Please enter a valid UUID for beacon feature. fid : '{fid}'.

🔹 7. Minor

  • Required: Yes
  • Conditions:

    → Must not be -1 → Must be between 0 and 65535 (UInt16 range)

  • Error Message:

    → Please enter a valid minor for beacon feature. fid : '{fid}'.

🔹 8. Major

  • Required: Yes
  • Conditions:

    → Must not be -1 → Must be between 0 and 65535 (UInt16 range)

  • Error Message:

    → Please enter a valid major for beacon feature. fid : '{fid}'.

🔹 9. Beacon Uniqueness Check

  • Purpose: Ensures that each beacon (uuid-major-minor) is unique per client.
  • Mechanism:

    → A beacon key is generated using the combination of uuid, major, and minor.

    → This key is checked against the in-memory cache for duplicates.

    → If the key exists and belongs to a different fid, it's considered a conflict.

  • Error Message:

    → The beacon already exists with another feature. fid : '{fid}'.

🔹 10. Feature Movement Validation

If feature is being moved to another site (sid differs from request siteIdentifier):

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

  • Feature must not already exist under target site:
    → "The feature 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 feature data ingestion.