JSON

JSON (JavaScript Object Notation) は一般的な軽量データ交換形式です。 ArcGIS Velocity は、さまざまなソースの IoT (Internet of Things) 観測データから生成された JSON を使用できます。

JSON は次のタイプのフィードとデータ ソースのデータ形式としてサポートされています。

  • フィード - Azure Event Hub、Azure Service Bus、AWS IoT、Cisco Edge Intelligence、HTTP ポーラー、HTTP 受信機、Kafka、WebSocket、RabbitMQ、MQTT
  • データ ソース - Azure Blob ストレージ、Amazon S3、HTTP ポーラー

JSON 構成の指定

フィードまたはデータ ソースの構成時に、使用されているデータのタイプを特定するためにサンプリングが行われます。 サンプリングによってデータが JSON 形式であることが特定された場合、次の JSON 構成の追加のパラメーターを指定できます。

ルート ノード

該当する場合、メッセージが存在する JSON 構造のルート ノードを指定します。 JSON 構造がルート レベルですべてのメッセージを配列に格納する場合は、空白のままにします。 たとえば、複数のレベルとオブジェクトから成るデータを表示する JSON の例を次に示します。

{
  "requestInfo": {
    "requestTime": 1573591345,
    "requestingUser": "Greg Smith"
  },
  "responseInfo": {
    "dataLastUpdated": 1573239432
  },
  "sensorData": [{
    "vehicleID": "17256",
    "driverName": "Peter Jones",
    "latitude": 35.21027,
    "longitude": -81.291326,
    "speed": 64.3,
    "heading": 161.34,
    "status": "Out for delivery",
    "lastBreak": 1573591581
  }, {
    "vehicleID": "11954",
    "driverName": "Frank Jenkins",
    "latitude": 35.23425,
    "longitude": -81.092657,
    "speed": 25.8,
    "heading": 54.64,
    "status": "Returning to warehouse",
    "lastBreak": 1573581253
  }]
}

sensorData のルート ノードが指定されている場合、次のデータが Velocity で使用されます。

[{
  "vehicleID": "17256",
  "driverName": "Peter Jones",
  "latitude": 35.21027,
  "longitude": -81.291326,
  "speed": 64.3,
  "heading": 161.34,
  "status": "Out for delivery",
  "lastBreak": 1573591581
}, {
  "vehicleID": "11954",
  "driverName": "Frank Jenkins",
  "latitude": 35.23425,
  "longitude": -81.092657,
  "speed": 25.8,
  "heading": 54.64,
  "status": "Returning to warehouse",
  "lastBreak": 1573581253
}]

この結果、以下のスキーマが作成されます。

sensorData ルート ノードを指定した場合に生成された [スキーマの確認] ページ

フラット化

[フラット化] パラメーターは、ネストされた JSON を別のフィールドに分割するかどうかを決定します。 新しいフィールドには、上位オブジェクトにアンダースコアと下位オブジェクトを付加した名前が付きます。 以下の例では、position オブジェクトに latitude オブジェクトと longitude オブジェクトが含まれています。 フラット化すると、position オブジェクトが position_latitudeposition_longitude の 2 つのフィールドに分割されます。

複数の深さレベルでネストされている JSON をフラットにすることができます。 フラット化された新しいフィールドの名前には、最も深いレベルのオブジェクトに到達するまで、オブジェクト名とアンダースコアが付加されます。

たとえば、position オブジェクトと vehicleInformation オブジェクトを表示する JSON の例を次に示します。

[{
  "vehicleID": "17256",
  "driverName": "Peter Jones",
  "position": {
    "latitude": 35.21027,
    "longitude": -81.291326
  },
  "vehicleInformation": {
    "lastService": 1571431836,
    "warningCodes": 2
  },
  "speed": 64.3,
  "heading": 161.34,
  "status": "Out for delivery",
  "lastBreak": 1573591581
}, {
  "vehicleID": "11954",
  "driverName": "Frank Jenkins",
  "position": {
    "latitude": 35.23425,
    "longitude": -81.092657
  },
  "vehicleInformation": {
    "lastService": 1560531836,
    "warningCodes": 2
  },
  "speed": 25.8,
  "heading": 54.64,
  "status": "Returning to warehouse",
  "lastBreak": 1573581253
}]

[フラット化] パラメーターがオンになっている場合、上の例に示した JSON は次のように処理され、position オブジェクトと vehicleInformation オブジェクト内の各エレメントがそれぞれのフィールドに分割されます。

[{
  "vehicleID": "17256",
  "driverName": "Peter Jones",
  "position_latitude": 35.21027,
  "position_longitude": -81.291326,
  "vehicleInformation_lastService": 1571431836,
  "vehicleInformation_warningCodes": 2,
  "speed": 64.3,
  "heading": 161.34,
  "status": "Out for delivery",
  "lastBreak": 1573591581
}, {
  "vehicleID": "11954",
  "driverName": "Frank Jenkins",
  "position_latitude": 35.23425,
  "position_longitude": -81.092657,
  "vehicleInformation_lastService": 1560531836,
  "vehicleInformation_warningCodes": 2,
  "speed": 25.8,
  "heading": 54.64,
  "status": "Returning to warehouse",
  "lastBreak": 1573581253
}]

スキーマは以下の図のように使用されます。 フィールド名 vehicleInformation_lastService および vehicleInformation_warningCodes はユーザー インターフェイスでは一部が切れて表示されていますが、アプリケーションでは変更されません。

フラット化された JSON から生成された [スキーマの確認] ページ

フラット化の適用除外

[フラット化の適用除外] パラメーターでは、単一の文字列要素のままにし、別々のフィールドには分割しない JSON エレメントの名前を 1 つ以上指定できます (例: 配列を表す JSON オブジェクトや他の要素が格納されているオブジェクト)。 次に示す JSON の例について考えてみましょう。

[{
  "ship_ID": "17256",
  "call_sign": "3FCB8",
  "ship_type": "Cargo",
  "last_known_position": {
    "timestamp": "2019-06-24T18:30:56+00:00",
    "geometry": {
      "type": "Point",
      "coordinates": [
        79.19315,
        7.18374
      ]
    },
    "heading": 109
  }
}, {
  "ship_ID": "29435",
  "call_sign": "9GEF3",
  "ship_type": "Passenger",
  "last_known_position": {
    "timestamp": "2019-06-24T18:30:47+00:00",
    "geometry": {
      "type": "Point",
      "coordinates": [
        73.24954,
        10.43512
      ]
    },
    "heading": 120
  }
}]

[フラット化] パラメーターがオンになっていて、geometry[フラット化の適用除外] 値が指定されている場合、上記の例に示す JSON は以下の図のように処理されます。 last_known_position_geometry フィールドでは、JSON オブジェクトはフラット化によって分割されていません。 これは、[フラット化の適用除外] パラメーターで元の JSON エレメント geometry が指定されているためです。 これは JSON オブジェクトを維持する必要がある場合に便利です。 通常、これはジオメトリ オブジェクトがフィーチャの空間位置を表す場合に当てはまります。 この場合、この属性は GeoJSON ジオメトリ形式です。

[{
  "ship_ID": "17256",
  "call_sign": "3FCB8",
  "ship_type": "Cargo",
  "last_known_position_timestamp": "2019-06-24T18:30:56+00:00",
  "last_known_position_geometry": {
    "type": "Point",
    "coordinates": [
      79.19315,
      7.18374
    ]
  },
  "last_known_position_heading": 109
}, {
  "ship_ID": "29435",
  "call_sign": "9GEF3",
  "ship_type": "Passenger",
  "last_known_position_timestamp": "2019-06-24T18:30:47+00:00",
  "last_known_position_geometry": {
    "type": "Point",
    "coordinates": [
      73.24954,
      10.43512
    ]
  },
  "last_known_position_heading": 120
}]

以下の図に示すようなスキーマが使用され、フィードまたはデータ ソースの位置情報を単一のフィールドから取得するように設定できます。

ジオメトリ フィールドがフラット化の適用除外としている場合、フラット化された JSON から生成された [スキーマの確認] ページ

配列のフラット化

[配列のフラット化] パラメーターは、配列を別のフィールドにフラット化するかどうかを決定します。 新しいフィールドには、arrayName 値にアンダースコアと配列オブジェクトの数を付加した名前が付きます。 配列がオブジェクトの配列である場合、フィールド名にはアンダースコアとその値に関連する名前も付加されます。 オブジェクトの配列をフラット化する際、JSON を複数の深さレベルでネストすることができます。 フラット化された新しいフィールドの名前には、最も深いオブジェクトに到達するまで、オブジェクト名とアンダースコアが付加されます。

たとえば、cargoInformation 配列オブジェクトを表示する JSON の例を次に示します。

{
    "name": "iss",
    "id": 25544,
    "latitude": -13.210305423781,
    "longitude": -118.47517068897,
    "velocity": 27564.442053654,
    "visibility": "daylight",
    "cargoInformation": [{
            "sensorsID": 1,
            "age": 5432
        }, {
            "sensorsID": 2,
            "age": 9876
        }
    ],
    "footprint": 4521.609615023,
    "timestamp": 1654531549,
    "daynum": 2459737.170706,
    "solar_lat": 22.696540649846,
    "solar_lon": 298.23268983658,
    "units": "kilometers"
}

[配列のフラット化] パラメーターがオンになっている場合、上の例に示した JSON は次のように処理され、貨物情報オブジェクト内の各エレメントがそれぞれのフィールドに分割されます。

{
    "name": "iss",
    "id": 25544,
    "latitude": -13.210305423781,
    "longitude": -118.47517068897,
    "velocity": 27564.442053654,
    "visibility": "daylight",
    "cargoInformation_0_sensorsID": 1,
    "cargoInformation_0_age": 5432,
    "cargoInformation_1_sensorsID": 2,
    "cargoInformation_1_age": 9876,
    "footprint": 4521.609615023,
    "timestamp": 1654531549,
    "daynum": 2459737.170706,
    "solar_lat": 22.696540649846,
    "solar_lon": 298.23268983658,
    "units": "kilometers"
}

スキーマは以下の図のように使用されます。 フィールド名 cargoInformation はユーザー インターフェイスでは一部が切れて表示されていますが、アプリケーションでは変更されません。

JSON 形式の配列のフラット化

配列のフラット化の適用除外

[配列のフラット化の適用除外] パラメーターでは、単一の文字列要素のままにし、別々のフィールドには分割しない JSON 配列の名前を 1 つ以上指定できます。 次に示す JSON の例について考えてみましょう。

{
    "name": "iss",
    "id": 25544,
    "latitude": -13.210305423781,
    "longitude": -118.47517068897,
    "velocity": 27564.442053654,
    "visibility": "daylight",
    "cargoInformation": [{
            "sensorsID": 1,
            "age": 5432
        }, {
            "sensorsID": 2,
            "age": 9876
        }
    ],
    "sensorValues": [1,2,3,4,5],
    "footprint": 4521.609615023,
    "timestamp": 1654531549,
    "daynum": 2459737.170706,
    "solar_lat": 22.696540649846,
    "solar_lon": 298.23268983658,
    "units": "kilometers"
}

[配列のフラット化] パラメーターがオンになっていて、sensorValues[配列のフラット化の適用除外] 値が指定されている場合、上記の例に示す JSON は以下の図のように処理されます。 sensorValues 配列では、配列オブジェクトはフラット化によって分割されず、文字列のままです。 複数の配列をフラット化の適用から除外するには、[配列のフラット化の適用除外] パラメーターにカンマで区切って指定します。

{
    "name": "iss",
    "id": 25544,
    "latitude": -13.210305423781,
    "longitude": -118.47517068897,
    "velocity": 27564.442053654,
    "visibility": "daylight",
    "cargoInformation_0_sensorsID": 1,
    "cargoInformation_0_age": 5432,
    "cargoInformation_1_sensorsID": 2,
    "cargoInformation_1_age": 9876,
    "sensorValues": [1,2,3,4,5],
    "footprint": 4521.609615023,
    "timestamp": 1654531549,
    "daynum": 2459737.170706,
    "solar_lat": 22.696540649846,
    "solar_lon": 298.23268983658,
    "units": "kilometers"
}

スキーマは以下の図のように使用されます。

JSON 配列のフラット化の適用除外

検討事項および制限事項

Velocity で JSON 形式のデータを使って作業する場合、以下に示す情報と制限を考慮してください。

配列を含む JSON データ

JSON では配列を柔軟に使用できますが、長さが不確定なため、JSON データから ArcGIS のフィーチャを構築するときに困難な点があります。 ドキュメント全体または定義されたルート ノードがオブジェクトの配列である場合、個々のオブジェクトは別のフィーチャとして扱われます。 JSON オブジェクト内の配列は、文字列として取得されます。 以後の文字列の処理は、解析ツールを使用して実行できます。

NULL データ値

JSON 形式では、データは名前と値のペアによって表されます。 値が NULL の場合、JSON 形式でデータを作成するアプリケーションの多くは、名前オブジェクトを省略します。

これはフィードまたはデータ ソースを初めて構成または編集する場合に意味があります。 Velocity は、データ形式とスキーマを決定するために、データ ストリームまたはファイルをサンプリングします。 サンプリング プロセスによって返されたすべてのサンプルの値が NULL であることが原因で JSON 要素が欠落している場合、それらのフィールドはフィードまたはソース データのスキーマから漏れてしまいます。

その結果、後で受信したメッセージにそれらの JSON 要素のデータ値がある場合でも、そのメッセージを解析して、Velocity でフィードまたは解析によって処理可能な観測値またはレコードに変換することはできません。

生成されたフィールド タイプ

一般的な JSON データはタイプが厳密に指定されていないため、場合によっては、サンプルから生成されたフィールド タイプを修正する必要があります。 ただし、フィールド タイプを変更する際には注意が必要です。 より包括的なフィールド タイプを指定することをお勧めします。 たとえば、小さなサンプル セットでは、特定のフィールド値が Float32 ではなく Float64 であることが明らかにならない場合があります。

また、フィールドを浮動小数タイプ (Float64 または Float32) から整数タイプ (Int64 または Int32) に変更することはお勧めしません。 数値をリアルタイムで変換するために、フィールド タイプを変更することもお勧めしません。 JSON データの場合、浮動小数から整数にダウングレードすると、値の小数部分が丸めなしで切り捨てられます。 数値を変換するには、フィールド演算またはフィールドの割り当てを使用します。

JSON ファイルのサイズ

ベスト プラクティスとして、Velocity での JSON ファイルのサイズは、1 ファイルあたり 100 MB 以下に維持する必要があります。 データ量が多い場合、各ファイルのサイズが 100 MB 以下になるようにファイルを分割します。