概要
このポリシーは、メッセージを拡張マークアップ言語(XML)形式から JavaScript Object Notation(JSON)に変換します。これにより、メッセージの変換方法を制御するための選択肢が多彩になります。
XML 形式のレスポンスを JSON 形式のレスポンスに変換することが目的であると仮定した場合、このポリシーはレスポンス フロー(たとえば Response / ProxyEndpoint / PostFlow)に接続されます。
説明
代表的な仲介シナリオでは、多くの場合、受信リクエスト フローでの JSON to XML ポリシーを送信レスポンス フローでの XML to JSON ポリシーとペアで使用されます。ポリシーをこのように結び付けることで、XML のみをネイティブ サポートするバックエンド サービスに対して JSON API を公開できます。
API が、JSON あるいは XML を必要とする可能性のある多様なクライアント アプリで消費されるシナリオでは、JSON to XML ポリシーと XML to JSON ポリシーを条件に応じて実行するよう構成することで、レスポンス形式を動的に設定できます。このシナリオの実装については、フロー変数と条件をご覧ください。
サンプル
JSON と XML の間の変換について詳しくは、http://community.apigee.com/articles/1839/converting-between-xml-and-json-what-you-need-to-k.html をご覧ください。
レスポンスを変換する
<XMLToJSON name="ConvertToJSON"> <Options> </Options> <OutputVariable>response</OutputVariable> <Source>response</Source> </XMLToJSON>
この構成(XML を JSON に変換するために必要な最小限の構成)は、XML 形式のレスポンス メッセージをソースとして受け取り、出力変数 response に入力される JSON 形式のメッセージを作成します。Edge はこの変数の内容を、自動的に次の処理ステップのメッセージとして使用します。
要素リファレンス
このポリシーで構成できる要素と属性は、以下のとおりです。
<XMLToJSON async="false" continueOnError="false" enabled="true" name="XML-to-JSON-1"> <DisplayName>XML to JSON 1</DisplayName> <Source>response</Source> <OutputVariable>response</OutputVariable> <Options> <RecognizeNumber>true</RecognizeNumber> <RecognizeBoolean>true</RecognizeBoolean> <RecognizeNull>true</RecognizeNull> <NullValue>NULL</NullValue> <NamespaceBlockName>#namespaces</NamespaceBlockName> <DefaultNamespaceNodeName>&</DefaultNamespaceNodeName> <NamespaceSeparator>***</NamespaceSeparator> <TextAlwaysAsProperty>true</TextAlwaysAsProperty> <TextNodeName>TEXT</TextNodeName> <AttributeBlockName>FOO_BLOCK</AttributeBlockName> <AttributePrefix>BAR_</AttributePrefix> <OutputPrefix>PREFIX_</OutputPrefix> <OutputSuffix>_SUFFIX</OutputSuffix> <StripLevels>2</StripLevels> <TreatAsArray> <Path unwrap="true">teachers/teacher/studentnames/name</Path> </TreatAsArray> </Options> <!-- Use Options or Format, not both --> <Format>yahoo</Format> </XMLToJSON>
<XMLtoJSON> 属性
<XMLtoJSON async="false" continueOnError="false" enabled="true" name="XML-to-JSON-1">
次の表に、すべてのポリシーの親要素に共通する属性を示します。
| 属性 | 説明 | デフォルト | 要否 |
|---|---|---|---|
name |
ポリシーの内部名。 管理 UI プロキシ エディタで |
なし | 必須 |
continueOnError |
ポリシーが失敗した場合にエラーを返すには、 ポリシーが失敗した後もフローの実行を続行する場合は、 |
false | 省略可 |
enabled |
ポリシーを適用するには、 ポリシーを無効にするには、 |
true | 省略可 |
async |
この属性は非推奨となりました。 |
false | 非推奨 |
<DisplayName> 要素
管理 UI プロキシ エディタで name 属性と一緒に使用して、ポリシーのラベルに使用する自然言語名を指定します。
<DisplayName>Policy Display Name</DisplayName>
| デフォルト |
なし この要素を省略した場合、ポリシーの |
|---|---|
| 要否 | 省略可 |
| タイプ | 文字列 |
<Source> 要素
JSON に変換する XML メッセージを含む変数、リクエスト、またはレスポンスです。
ソース メッセージの HTTP Content-type ヘッダーを application/xml に設定する必要があります。設定されていない場合、ポリシーは適用されません。
<Source> が定義されていない場合は、メッセージとして処理されます(ポリシーがリクエスト フローに接続されている場合はリクエスト、ポリシーがレスポンス フローに接続されている場合はレスポンスに解決される)。
ソース変数を解決できない場合、あるいはメッセージ以外のタイプに解決される場合、ポリシーはエラーを返します。
<Source>response</Source>
| デフォルト | リクエストまたはレスポンス(ポリシーが API プロキシフローに追加されている場所によって決まる)。 |
| 要否 | 省略可 |
| 型 | メッセージ |
<OutputVariable> 要素
XML to JSON 形式変換の出力を格納します。これは通常はソースと同じ値です。つまり、通常は XML レスポンスが JSON レスポンスに変換されます。
XML メッセージのペイロードが解析されて JSON に変換され、XML 形式のメッセージの HTTP Content-type ヘッダーは application/json に設定されます。
OutputVariable が指定されていない場合、source は OutputVariable として扱われます。たとえば、source が response である場合、OutputVariable のデフォルトは response になります。
<OutputVariable>response</OutputVariable>
| デフォルト | リクエストまたはレスポンス(ポリシーが API プロキシフローに追加されている場所によって決まる)。 |
| 要否 | <Source> 要素で定義された変数が文字列型の場合、この要素は必須です。 |
| 型 | メッセージ |
<Options>
Options により、XML から JSON への変換を制御できます。特定の変換設定を追加できる <Options> グループ、または事前定義オプションのテンプレートを参照できる <Format> 要素を使用します。<Options> と <Format> の両方を使用することはできません。
<Format> を使用しない場合は <Options> が必要です。
<Options>/<RecognizeNumber> 要素
true の場合、XML ペイロードの数値フィールドは元の形式を維持します。
<RecognizeNumber>true</RecognizeNumber>
以下の XML の例を考えてみましょう。
<a> <b>100</b> <c>value</c> </a>
true の場合、次のように変換されます。
{
"a": {
"b": 100,
"c": "value"
}
}false の場合、次のように変換されます。
{
"a": {
"b": "100",
"c": "value"
}
}| デフォルト | false |
| 要否 | 省略可 |
| 型 | ブール値 |
<Options>/<RecognizeBoolean> 要素
変換の際に true/false ブール値が維持され、文字列に変換されません。
<RecognizeBoolean>true</RecognizeBoolean>
次の XML 例の場合、以下のように変換されます。
<a> <b>true</b> <c>value</c> </a>
true の場合、次のように変換されます。
{
"a": {
"b": true,
"c": "value"
}
}false の場合、次のように変換されます。
{
"a": {
"b": "true",
"c": "value"
}
}| デフォルト | false |
| 要否 | 省略可 |
| 型 | ブール値 |
<Options>/<RecognizeNull> 要素
空の値を null 値に変換できます。
<RecognizeNull>true</RecognizeNull>
次の XML の場合、以下のように変換されます。
<a> <b></b> <c>value</c> </a>
true の場合、次のように変換されます。
{
"a": {
"b": null,
"c": "value"
}
}false の場合、次のように変換されます。
{
"a": {
"b": {},
"c": "value"
}
}| デフォルト | false |
| 要否 | 省略可 |
| 型 | ブール値 |
<Options>/<NullValue> 要素
変換されるメッセージ内の null 値を構成するものを示します。デフォルトでは、値は NULL です。
<NullValue>NULL</NullValue>
| デフォルト | NULL |
| 要否 | 省略可 |
| 型 | 文字列 |
<Options>/<NamespaceBlockName> 要素
<Options>/<DefaultNamespaceNodeName> 要素
<Options>/<NamespaceSeparator> 要素
これらの要素を一緒に使用します。
<NamespaceBlockName>#namespaces</NamespaceBlockName> <DefaultNamespaceNodeName>&</DefaultNamespaceNodeName> <NamespaceSeparator>***</NamespaceSeparator>
以下の XML の例を考えてみましょう。
<a xmlns="http://ns.com" xmlns:ns1="http://ns1.com"> <ns1:b>value</ns1:b> </a>
NamespaceSeparator が指定されていない場合、次の JSON 構造が生成されます。
{
"a": {
"b": "value"
}
}NamespaceBlockName 要素、DefaultNamespaceNodeName 要素、NamespaceSeparator 要素がそれぞれ #namespaces、&、*** として指定されている場合、次の JSON 構造が生成されます。
{
"a": {
"#namespaces": {
"&": "http://ns.com",
"ns1": "http://ns1.com"
},
"ns1***b": "value"
}
}| デフォルト | 上の例をご覧ください。 |
| 要否 | 省略可 ただし、 <NamespaceBlockName> を指定する場合は、その他の 2 つの要素も指定する必要があります。 |
| 型 | 文字列 |
<Options>/<TextAlwaysAsProperty> 要素
<Options>/<TextNodeName> 要素
これらの要素を一緒に使用します。
true に設定すると、XML 要素のコンテンツが文字列プロパティに変換されます。
<TextAlwaysAsProperty>true</TextAlwaysAsProperty> <TextNodeName>TEXT</TextNodeName>
次の XML の場合、以下のように変換されます。
<a> <b>value1</b> <c>value2<d>value3</d>value4</c> </a>
TextAlwaysAsProperty が true に設定され、TextNodeName が TEXT として指定されている場合、次の JSON 構造が生成されます。
{
"a": {
"b": {
"TEXT": "value1"
},
"c": {
"TEXT": [
"value2",
"value4"
],
"d": {
"TEXT": "value3"
}
}
}
}TextAlwaysAsProperty が false に設定され、TextNodeName が TEXT として指定されている場合、次の JSON 構造が生成されます。
{
"a": {
"b": "value1",
"c": {
"TEXT": [
"value2",
"value4"
],
{
"d": "value3",
}
}
}| デフォルト | <TextAlwaysAsProperty>: false <TextNodeName>: 該当なし |
| 要否 | 省略可 |
| 型 | <TextAlwaysAsProperty>: ブール値<TextNodeName>: 文字列 |
<Options>/<AttributeBlockName> 要素
<Options>/<AttributePrefix> 要素
これらの要素を一緒に使用します。
値を JSON ブロックにグループ化して、属性名に接頭辞を追加できます。
<AttributeBlockName>FOO_BLOCK</AttributeBlockName> <AttributePrefix>BAR_</AttributePrefix>
以下の XML の例を考えてみましょう。
<a attrib1="value1" attrib2="value2"/>
XML to JSON の例で定義されているように、両方の属性(AttributeBlockName と AttributePrefix)が指定されている場合、次の JSON 構造が生成されます。
{
"a": {
"FOO_BLOCK": {
"BAR_attrib1": "value1",
"BAR_attrib2": "value2"
}
}
}AttributeBlockName のみを指定すると、次の JSON 構造が生成されます。
{
"a": {
"FOO_BLOCK": {
"attrib1": "value1",
"attrib2": "value2"
}
}
}AttributePrefix のみを指定すると、次の JSON 構造が生成されます。
{
"a": {
"BAR_attrib1": "value1",
"BAR_attrib2": "value2"
}
}どちらも指定されていない場合、次の JSON 構造が生成されます。
{
"a": {
"attrib1": "value1",
"attrib2": "value2"
}
}| デフォルト | 上の例をご覧ください。 |
| 要否 | 省略可 |
| 型 | 文字列 |
<Options>/<OutputPrefix> 要素
<Options>/<OutputSuffix> 要素
これらの要素を一緒に使用します。
<OutputPrefix>PREFIX_</OutputPrefix> <OutputSuffix>_SUFFIX</OutputSuffix>
以下の XML の例を考えてみましょう。
<a>value</a>
XML to JSON の例で定義されているように、両方の属性(OutputPrefix と OutputSuffix)が指定されている場合、次の JSON 構造が生成されます。
PREFIX_{
"a": "value"
}_SUFFIXOutputPrefix のみを指定すると、次の JSON 構造が生成されます。
PREFIX_{
"a" : "value"
}OutputSuffix のみを指定すると、次の JSON 構造が生成されます。
{
"a" : "value"
}_SUFFIXOutputPrefix と OutputSuffix のいずれも指定されていない場合、次の JSON 構造が生成されます。
{
"a": "value"
}| デフォルト | 上の例をご覧ください。 |
| 要否 | 省略可 |
| 型 | 文字列 |
<Options>/<StripLevels> 要素
<Options>
<StripLevels>4</StripLevels>
</Options>SOAP などの XML ペイロードには、変換後の JSON に含めたくない親レベルが多数あることがあります。以下の例では、SOAP レスポンスに多数のレベルが含まれています。
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/Schemata-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <GetCityWeatherByZIPResponse xmlns="http://ws.cdyne.com/WeatherWS/"> <GetCityWeatherByZIPResult> <State>CO</State> <City>Denver</City> <Description>Sunny</Description> <Temperature>62</Temperature> </GetCityWeatherByZIPResult> </GetCityWeatherByZIPResponse> </soap:Body> </soap:Envelope>
State、City、Description、および Temperature レベルに達するまでに 4 つのレベルがあります。<StripLevels> を使用しない場合、変換した後の JSON レスポンスは次のようになります。
{
"Envelope" : {
"Body" : {
"GetCityWeatherByZIPResponse" : {
"GetCityWeatherByZIPResult" : {
"State" : "CO",
"City" : "Denver",
"Description" : "Sunny",
"Temperature" : "62"
}
}
}
}
}JSON レスポンスの最初の 4 つのレベルを削除する場合は、<StripLevels>4</StripLevels> を設定します。これにより、次の JSON が生成されます。
{
"State" : "CO",
"City" : "Denver",
"Description" : "Sunny",
"Temperature" : "62"
}除去できるレベルは、複数の子を含んでいる最初の要素までです。これが意味するところについては、より複雑な JSON の例を見てみましょう。
{
"Envelope" : {
"Body" : {
"GetCityForecastByZIPResponse" : {
"GetCityForecastByZIPResult" : {
"ResponseText" : "City Found",
"ForecastResult" : {
"Forecast" : [
{
"ProbabilityOfPrecipiation" : {
"Nighttime" : "00",
"Daytime" : 10
} ...この例のレベル 3 は GetCityForecastByZIPResponse です。子要素は 1 つだけです。したがって、<StripLevels>3</StripLevels> を使用する(最初の 3 つのレベルを削除する)場合、JSON は次のようになります。
{
"GetCityForecastByZIPResult" : {
"ResponseText" : "City Found",
"ForecastResult" : {
"Forecast" : [
{
"ProbabilityOfPrecipiation" : {
"Nighttime" : "00",
"Daytime" : 10
} ...GetCityForecastByZIPResult には複数の子要素があります。これが複数の子要素を持つ最初の要素であるため、この最後のレベルを <StripLevels>4</StripLevels> を使用して削除できます。これにより、次の JSON が得られます。
{
"ResponseText" : "City Found",
"ForecastResult" : {
"Forecast" : [
{
"ProbabilityOfPrecipiation" : {
"Nighttime" : "00",
"Daytime" : 10
} ...レベル 4 が複数の子を含んだ最初のレベルであるため、これより下のレベルは除去できません。除去レベルを 5、6、7 といった具合に設定しても、引き続き上記のレスポンスが取得されます。
| デフォルト | 0 (レベル除去なし) |
| 要否 | 省略可 |
| 型 | 整数 |
<Options>/<TreatAsArray>/<Path> 要素
<Options>
<TreatAsArray>
<Path unwrap="true">teachers/teacher/studentnames/name</Path>
</TreatAsArray>
</Options>これらの要素の組み合わせにより、XML ドキュメントの値を確実に JSON 配列に入れることができます。これは、たとえば子要素の数が(1 から複数まで)異なる可能性があり、値が常に配列内に入るようにする場合に役立ちます。こうすることで、配列からデータを毎回同じように取得できるため、コードを安定させることができます。たとえば、$.teachers.teacher.studentnames[0] は配列内の値の数に関係なく、配列内の最初の生徒名の値を取得します。
XML to JSON のデフォルトの動作を確認し、<TreatAsArray>/<Path> を使用して出力を制御する方法を見てみましょう。
XML ドキュメントに複数の子の値を持つ要素が含まれている場合(通常は要素の maxOccurs='unbounded' のスキーマに基づきます)、XML to JSON ポリシーは自動的に配列に格納します。たとえば、次の XML ブロックを見てみましょう。
<teacher>
<name>teacherA</name>
<studentnames>
<name>student1</name>
<name>student2</name>
</studentnames>
</teacher>これは、特殊なポリシー構成なしで、以下の JSON に自動的に変換されます。
{
"teachers" : {
"teacher" : {
"name" : "teacherA",
"studentnames" : {
"name" : [
"student1",
"student2"
]}
}
}
}2 つの生徒名が配列に入っています。
ただし、1 つの生徒しか XML ドキュメントに存在しない場合、XML to JSON ポリシーは自動的にこの値を、文字列の配列でなく、ひとつの文字列として扱います。これを、下の例で示します。
{
"teachers" : {
"teacher" : {
"name" : "teacherA",
"studentnames" : {
"name" : "student1"
}
}
}
}これまでの例では、同様のデータが、あるものは配列に、またあるものはひとつの文字列にと、さまざまな方法で変換されていました。ここで、<TreatAsArray>/<Path> 要素を使用して出力を制御できます。たとえば、生徒名の値が 1 つしかなくても、常に配列に入れられるようにできます。このように構成するには、配列に入れたい値を持つ要素へのパスを、以下のようにして見つけます。
<Options>
<TreatAsArray>
<Path>teachers/teacher/studentnames/name</Path>
</TreatAsArray>
</Options>上の構成によって、次のような JSON が作成されます。
{
"teachers" : {
"teacher" : {
"name" : "teacherA",
"studentnames" : {
"name" : ["student1"]
}
]
}
}
}student1 が配列の中に入るようになりました。これで、生徒が 1 人か複数かにかかわらず、次の JSONPath を使用してコード内の JSON 配列から取得できます。
$.teachers.teacher.studentnames.name[0]
<Path> 要素にも unwrap 属性があります。これについては次のセクションで説明します。
| デフォルト | なし |
| 要否 | 省略可 |
| 型 | 文字列 |
属性
<Options>
<TreatAsArray>
<Path unwrap="true">teachers/teacher/studentnames/name</Path>
</TreatAsArray>
</Options>| 属性 | 説明 | 要否 | 型 |
|---|---|---|---|
| unwrap |
デフォルト: false JSON 出力から要素を削除します。これを使用することで、JSON を合理化、つまりフラット(「ラップ解除」)にします。値を取得するために必要な JSONPath も短くなります。たとえば、 以下に JSON の例を示します。 {
"teachers" : {
"teacher" : {
"name" : "teacherA",
"studentnames" : {
"name" : [
"student1",
"student2"
]}...この例では、 <TreatAsArray>
<Path unwrap="true">teachers/teacher</Path>
<Path unwrap="true">teachers/teacher/studentnames/name</Path>
</TreatAsArray>
{
"teachers" : [{
"name" : "teacherA",
"studentnames" : ["student1","student2"]
}]...
|
省略可 | ブール値 |
その他の例と機能のチュートリアルについては、次の Apigee コミュニティの記事をご覧ください: https://community.apigee.com/content/kbentry/33374/new-edge-minifeature-the-treatasarray-option-in-th.html。
<Format>
Format により、XML から JSON への変換を制御できるようになります。このトピックで説明した特定の Options 要素の組み合わせが含まれている、事前定義テンプレートの名前を入力します。事前定義された形式には次のものがあります。xml.com、yahoo、google、badgerFish。
<Format> 要素か <Options> グループのいずれかを使用します。<Format> と <Options> の両方は使用できません。
以下は、それぞれの事前定義テンプレートの形式定義です。
xml.com
<RecognizeNull>true</RecognizeNull> <TextNodeName>#text</TextNodeName> <AttributePrefix>@</AttributePrefix>
yahoo
<RecognizeNumber>true</RecognizeNumber> <TextNodeName>content</TextNodeName>
<TextNodeName>$t</TextNodeName> <NamespaceSeparator>$</NamespaceSeparator> <TextAlwaysAsProperty>true</TextAlwaysAsProperty>
badgerFish
<TextNodeName>$</TextNodeName> <TextAlwaysAsProperty>true</TextAlwaysAsProperty> <AttributePrefix>@</AttributePrefix> <NamespaceSeparator>:</NamespaceSeparator> <NamespaceBlockName>@xmlns</NamespaceBlockName> <DefaultNamespaceNodeName>$</DefaultNamespaceNodeName>
要素の構文:
<Format>yahoo</Format>
| デフォルト | 使用可能な形式の名前を入力します。xml.com、yahoo、google、badgerFish |
| 要否 | <Options> を使用しない場合は必須です。 |
| 型 | 文字列 |
スキーマ
エラー リファレンス
このセクションでは、このポリシーによってエラーがトリガーされたときに返される障害コードとエラー メッセージ、Edge によって設定される障害変数について説明します。 これは、障害に対処する障害ルールを作成するうえで重要な情報です。詳細については、ポリシーエラーについて知っておくべきことと障害の処理をご覧ください。
ランタイム エラー
このエラーは、ポリシーの実行時に発生することがあります。
| 障害コード | HTTP ステータス | 原因 | 修正 |
|---|---|---|---|
steps.xmltojson.ExecutionFailed |
500 | このエラーは、入力ペイロード(XML)が空、入力 XML が無効、または形式が正しくない場合に発生します。 | build |
steps.xmltojson.InCompatibleType |
500 | このエラーは、<Source> 要素で定義された変数の型と、<OutputVariable> 要素で定義された変数の型が異なる場合に発生します。<Source> 要素に含まれる変数の型と、<OutputVariable> 要素に含まれる変数の型は一致する必要があります。 |
build |
steps.xmltojson.InvalidSourceType |
500 | このエラーは、<Source> 要素の定義に使用される変数の型が無効な場合に発生します。有効な変数の型は、message と String です。 |
build |
steps.xmltojson.OutputVariableIsNotAvailable |
500 | このエラーは、XML to JSON ポリシーの <Source> 要素で指定された変数が String 型であり、<OutputVariable> 要素が定義されていない場合に発生します。<Source> 要素で定義された変数が String 型の場合、<OutputVariable> 要素は必須です。 |
build |
steps.xmltojson.SourceUnavailable |
500 | このエラーは、XML to JSON ポリシーの <Source> 要素で指定された message 変数が、次のいずれかである場合に発生します。
|
build |
デプロイエラー
以下のエラーは、このポリシーを含むプロキシをデプロイするときに発生することがあります。
| エラー名 | 原因 | 修正 |
|---|---|---|
EitherOptionOrFormat |
<Options> または <Format> のいずれかの要素が XML to JSON ポリシーに宣言されていない場合、API プロキシのデプロイは失敗します。 |
build |
UnknownFormat |
XML to JSON ポリシー内の <Format> 要素に不明な形式が定義されている場合、API プロキシのデプロイは失敗します。事前定義された形式には、xml.com、yahoo、google、badgerFish があります。 |
build |
障害変数
ランタイム エラーが発生すると、次の変数が設定されます。詳細については、ポリシーエラーについて知っておくべきことをご覧ください。
| 変数 | 説明 | 例 |
|---|---|---|
fault.name="fault_name" |
fault_name は、上記のランタイム エラーの表に記載されている障害の名前です。障害名は、障害コードの最後の部分です。 | fault.name = "SourceUnavailable" |
xmltojson.policy_name.failed |
policy_name は、障害が発生したポリシーのユーザー指定の名前です。 | xmltojson.XMLtoJSON-1.failed = true |
エラー レスポンスの例
{ "fault": { "faultstring": "XMLToJSON[XMLtoJSON-1]: Source xyz is not available", "detail": { "errorcode": "steps.xml2json.SourceUnavailable" } } }
障害ルールの例
<faultrule name="VariableOfNonMsgType"></faultrule><FaultRule name="XML to JSON Faults"> <Step> <Name>AM-SourceUnavailableMessage</Name> <Condition>(fault.name Matches "SourceUnavailable") </Condition> </Step> <Step> <Name>AM-BadXML</Name> <Condition>(fault.name = "ExecutionFailed")</Condition> </Step> <Condition>(xmltojson.XMLtoJSON-1.failed = true) </Condition> </FaultRule>
関連トピック
JSON to XML: JSON to XML ポリシー