diff --git a/SW.Bitween.Api/Services/MapperEnrichment.cs b/SW.Bitween.Api/Services/MapperEnrichment.cs index ad040150..944d2a40 100644 --- a/SW.Bitween.Api/Services/MapperEnrichment.cs +++ b/SW.Bitween.Api/Services/MapperEnrichment.cs @@ -17,8 +17,8 @@ namespace SW.Bitween; public static class MapperEnrichment { /// - /// The payload as the enrichment reads it: JToken.Parse, which throws on what is not JSON, - /// and null for JSON that is not an object (a root array, a string), which is not enriched. + /// The payload as the enrichment reads it: null for what is not a JSON object, which is not + /// enriched - other JSON (a root array, a string), and what is not JSON at all. /// /// /// says the object is the pipeline's shared parse, which @@ -35,7 +35,16 @@ public static JObject Read(XchangeFile file, out bool shared) shared = false; NativeAdapters.PayloadParseTally.Parsed(); - return JToken.Parse(file.Data) as JObject; + try + { + return JToken.Parse(file.Data) as JObject; + } + catch (JsonReaderException) + { + // XML or CSV from a receiver, read by a custom mapper. Failing it here failed every such + // exchange before its mapper ran, for values it had no use for. + return null; + } } /// diff --git a/SW.Bitween.Api/Services/XchangeService.cs b/SW.Bitween.Api/Services/XchangeService.cs index 6dd0638d..c93b2850 100644 --- a/SW.Bitween.Api/Services/XchangeService.cs +++ b/SW.Bitween.Api/Services/XchangeService.cs @@ -421,9 +421,7 @@ private async Task RunMapper(Xchange xchange, XchangeFile xchangeFi // A mapper that takes its context separately gets the payload exactly as it arrived. Anything // else keeps the enrichment below, unchanged - every template already written reads // __partner__ out of the payload, so this is load-bearing behaviour, not an implementation - // detail. Note the JToken.Parse: it runs before anything knows which mapper is configured, - // and it throws on a payload that is not JSON, which is why a mapper that wants to handle - // XML or CSV has to be able to opt out of this entire block. + // detail. A payload that is not JSON goes to the mapper as it arrived. string mappingContextJson = null; if (nativeAdapterDiscovery.MapperReceivesOwnContext(xchange.MapperId)) @@ -434,8 +432,8 @@ private async Task RunMapper(Xchange xchange, XchangeFile xchangeFi { // Inject __partner__ adapter properties into the input JSON so Scriban templates // can reference them as {{ __partner__?.propkey }} - // Only applies when the data is a JSON object; skip enrichment for non-object payloads - // (e.g. a receiver returning a JSON-encoded string). + // Only applies when the data is a JSON object; skip enrichment for anything else + // (e.g. a receiver returning a JSON-encoded string, or XML). var jObjEnriched = MapperEnrichment.Read(xchangeFile, out var shared); if (jObjEnriched != null) diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-bom.json.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-bom.json.txt index a9cd2c0e..c1cd3b17 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-bom.json.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-bom.json.txt @@ -9,7 +9,7 @@ Not valid JSON: Unexpected character encountered while parsing value: . Path === schema-xml Not valid XML: Data at the root level is invalid. Line 1, position 1. === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: . Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: . Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-deep.json.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-deep.json.txt index 3efdf5e2..670f0688 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-deep.json.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-deep.json.txt @@ -9,7 +9,7 @@ Not valid JSON: The reader's MaxDepth of 64 has been exceeded. Path 'd.d.d.d.d.d === schema-xml Not valid XML: Data at the root level is invalid. Line 1, position 1. === enriched -!Newtonsoft.Json.JsonReaderException: The reader's MaxDepth of 64 has been exceeded. Path 'd.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d', line 1, position 333. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: The reader's MaxDepth of 64 has been exceeded. Path 'd.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d', line 1, position 333. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-empty.json.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-empty.json.txt index 37fec09b..505aac0e 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-empty.json.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-empty.json.txt @@ -11,7 +11,7 @@ Not valid JSON: Error reading JToken from JsonReader. Path '', line 0, position === schema-xml Not valid XML: Root element is missing. === enriched -!Newtonsoft.Json.JsonReaderException: Error reading JToken from JsonReader. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Error reading JToken from JsonReader. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-invalid.json.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-invalid.json.txt index 2970304c..edf3b648 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-invalid.json.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-invalid.json.txt @@ -9,7 +9,7 @@ Not valid JSON: Unexpected end of content while loading JObject. Path 'id', line === schema-xml Not valid XML: Data at the root level is invalid. Line 1, position 1. === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected end of content while loading JObject. Path 'id', line 1, position 7. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected end of content while loading JObject. Path 'id', line 1, position 7. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-trailing-content.json.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-trailing-content.json.txt index 6c3b688c..8adfea52 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-trailing-content.json.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-trailing-content.json.txt @@ -9,7 +9,7 @@ Not valid JSON: Additional text encountered after finished reading JSON content: === schema-xml Not valid XML: Data at the root level is invalid. Line 1, position 1. === enriched -!Newtonsoft.Json.JsonReaderException: Additional text encountered after finished reading JSON content: {. Path '', line 1, position 13. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Additional text encountered after finished reading JSON content: {. Path '', line 1, position 13. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-trailing-garbage.json.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-trailing-garbage.json.txt index 496513ad..3bd65ade 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-trailing-garbage.json.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-trailing-garbage.json.txt @@ -9,7 +9,7 @@ Not valid JSON: Additional text encountered after finished reading JSON content: === schema-xml Not valid XML: Data at the root level is invalid. Line 1, position 1. === enriched -!Newtonsoft.Json.JsonReaderException: Additional text encountered after finished reading JSON content: x. Path '', line 1, position 12. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Additional text encountered after finished reading JSON content: x. Path '', line 1, position 12. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-whitespace-only.json.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-whitespace-only.json.txt index 2c47b2af..861518cf 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-whitespace-only.json.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/json-whitespace-only.json.txt @@ -11,7 +11,7 @@ Not valid JSON: Error reading JToken from JsonReader. Path '', line 2, position === schema-xml Not valid XML: Root element is missing. === enriched -!Newtonsoft.Json.JsonReaderException: Error reading JToken from JsonReader. Path '', line 2, position 1. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Error reading JToken from JsonReader. Path '', line 2, position 1. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/text-csv.txt.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/text-csv.txt.txt index 2459b58d..cd80263e 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/text-csv.txt.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/text-csv.txt.txt @@ -11,7 +11,7 @@ Not valid JSON: Unexpected character encountered while parsing value: i. Path '' === schema-xml Not valid XML: Data at the root level is invalid. Line 1, position 1. === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: i. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: i. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-bom.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-bom.xml.txt index f9415f64..80fc6589 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-bom.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-bom.xml.txt @@ -17,7 +17,7 @@ Not valid JSON: Unexpected character encountered while parsing value: . Path === schema-xml Not valid XML: Data at the root level is invalid. Line 1, position 1. === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: . Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: . Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-cdata.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-cdata.xml.txt index 9c7b10a4..1a155416 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-cdata.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-cdata.xml.txt @@ -17,7 +17,7 @@ Not valid JSON: Unexpected character encountered while parsing value: <. Path '' === schema-xml (valid) === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-dtd.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-dtd.xml.txt index 4986172a..cde5d061 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-dtd.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-dtd.xml.txt @@ -17,7 +17,7 @@ Not valid JSON: Unexpected character encountered while parsing value: <. Path '' === schema-xml Not valid XML: For security reasons DTD is prohibited in this XML document. To enable DTD processing set the DtdProcessing property on XmlReaderSettings to Parse and pass the settings into XmlReader.Create method. === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-entities.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-entities.xml.txt index 47d184fd..a26f0435 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-entities.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-entities.xml.txt @@ -12,7 +12,7 @@ Not valid JSON: Unexpected character encountered while parsing value: <. Path '' line 1, position 95: The element 'order' has invalid child element 'raw'. List of possible elements expected: 'lines'. Not valid XML: An error occurred while parsing EntityName. Line 1, position 104. === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-html-encoded.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-html-encoded.xml.txt index 05c35621..7ef0f2d9 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-html-encoded.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-html-encoded.xml.txt @@ -17,7 +17,7 @@ Not valid JSON: Unexpected character encountered while parsing value: &. Path '' === schema-xml Not valid XML: Data at the root level is invalid. Line 1, position 1. === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: &. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: &. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-invalid-chars.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-invalid-chars.xml.txt index f8e15854..d0d32844 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-invalid-chars.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-invalid-chars.xml.txt @@ -17,7 +17,7 @@ Not valid JSON: Unexpected character encountered while parsing value: <. Path '' === schema-xml Not valid XML: '', hexadecimal value 0x07, is an invalid character. Line 1, position 30. === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-invalid.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-invalid.xml.txt index a60b45bc..dc14faba 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-invalid.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-invalid.xml.txt @@ -11,7 +11,7 @@ Not valid JSON: Unexpected character encountered while parsing value: <. Path '' === schema-xml Not valid XML: The 'id' start tag on line 1 position 9 does not match the end tag of 'order'. Line 1, position 17. === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-namespaces.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-namespaces.xml.txt index dc7ad0d1..c2f75a2d 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-namespaces.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-namespaces.xml.txt @@ -17,7 +17,7 @@ Not valid JSON: Unexpected character encountered while parsing value: <. Path '' === schema-xml (valid) === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-order.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-order.xml.txt index debc746a..ac2f49cc 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-order.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-order.xml.txt @@ -17,7 +17,7 @@ Not valid JSON: Unexpected character encountered while parsing value: <. Path '' === schema-xml (valid) === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-plain.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-plain.xml.txt index 9f7e3fe3..9479e36f 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-plain.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-plain.xml.txt @@ -17,7 +17,7 @@ Not valid JSON: Unexpected character encountered while parsing value: <. Path '' === schema-xml (valid) === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-trailing-content.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-trailing-content.xml.txt index 2beb098a..b9e3c2d0 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-trailing-content.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-trailing-content.xml.txt @@ -11,7 +11,7 @@ Not valid JSON: Unexpected character encountered while parsing value: <. Path '' === schema-xml Not valid XML: There are multiple root elements. Line 1, position 30. === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. === scriban diff --git a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-utf16-declaration.xml.txt b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-utf16-declaration.xml.txt index e3d0748b..c86baf39 100644 --- a/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-utf16-declaration.xml.txt +++ b/SW.Bitween.UnitTests/PayloadParsing/Golden/expected/xml-utf16-declaration.xml.txt @@ -17,7 +17,7 @@ Not valid JSON: Unexpected character encountered while parsing value: <. Path '' === schema-xml (valid) === enriched -!Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. +(not an object, not enriched) === enriched-scriban !Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0. === scriban diff --git a/docs/caveats.md b/docs/caveats.md index fc4bc341..1803218f 100644 --- a/docs/caveats.md +++ b/docs/caveats.md @@ -23,7 +23,7 @@ These behaviours were found while documenting Bitween from its source code, and | Validators only run for API gateways and the legacy API call endpoint. | `Services/XchangeService.cs` | | Exchanges created by fan-out do not carry the parent's references. | `XchangeService.CreateXchangesForHits` | | A retry without reset keeps the response subscription but drops the response message type name. | `Domain/Xchange/Xchange.cs` | -| Mappers other than the rules-based mapper fail on payloads that are not JSON, and overwrite payload keys named `__partner__` or `__globals__`. | `XchangeService.RunMapper` | +| Mappers other than the rules-based mapper overwrite payload keys named `__partner__` or `__globals__`. | `XchangeService.RunMapper` | | An API gateway attached to an inactive subscription returns 404. | `Controllers/GatewayController.cs` | | Bulk retry includes exchanges that have no result yet, so work still in flight can run twice. Deliberate: after a broker outage those are the exchanges a bulk retry is for. | `Resources/Xchanges/BulkRetryPlanner.cs` | | The dashboard's *Failures to act on* tile says it covers 14 days, but counts failures of any age. | `ClientApp/src/pages/dashboard/DashboardPage.tsx` | diff --git a/docs/exchange-pipeline.md b/docs/exchange-pipeline.md index 37632bb6..604768c2 100644 --- a/docs/exchange-pipeline.md +++ b/docs/exchange-pipeline.md @@ -92,7 +92,7 @@ When the exchange has a mapper, the mapper turns the input into the output file. How the mapper sees partner and global values depends on the mapper. - The **rules-based mapper**, `NativeMapper`, receives partner and global values as separate context. The payload reaches it untouched, so it can map XML as well as JSON. -- **Every other mapper**, including the legacy JSON mapper and custom mappers, gets them written into the payload as `__partner__` and `__globals__` keys, and only when the payload is a JSON object. A payload that is not JSON fails the exchange before the mapper runs. A real payload key with either name is overwritten. +- **Every other mapper**, including the legacy JSON mapper and custom mappers, gets them written into the payload as `__partner__` and `__globals__` keys, and only when the payload is a JSON object. Any other payload, such as XML or CSV, reaches the mapper as it arrived. A real payload key with either name is overwritten. A mapper that returns nothing fails the exchange. See [Mapping](mapping.md).