Json Transformer
JsonTransformer.TransformToken - Test Examples
This document provides comprehensive examples for testing the TransformToken method in the JsonTransformer class.
Table of Contents
- Basic Field Extraction
- Nested Property Access
- Field Combination
- Wildcard Usage
- Array Element Mapping
- Type Casting
- Complex Transformations
- Nested Object Mapping with Literal Values
- JSONPath Filter Expressions
- FormData Field Extraction
- Edge Cases
Basic Field Extraction
Example 1: Simple Property Mapping
Source JSON:
{
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"age": 30
}
Pattern:
{
"name": "firstName",
"contact": "email",
"userAge": "age"
}
Expected Result:
{
"name": "John",
"contact": "john.doe@example.com",
"userAge": 30
}
Nested Property Access
Example 2: Deep Nested Object Access
Source JSON:
{
"user": {
"profile": {
"personal": {
"firstName": "Jane",
"lastName": "Smith"
},
"contact": {
"email": "jane.smith@example.com",
"phone": "+1-555-0123"
}
},
"settings": {
"theme": "dark",
"language": "en"
}
}
}
Pattern:
{
"fullName": "user.profile.personal.firstName",
"emailAddress": "user.profile.contact.email",
"phoneNumber": "user.profile.contact.phone",
"preferredTheme": "user.settings.theme"
}
Expected Result:
{
"fullName": "Jane",
"emailAddress": "jane.smith@example.com",
"phoneNumber": "+1-555-0123",
"preferredTheme": "dark"
}
Field Combination
Example 3: Combining Multiple Fields
Source JSON:
{
"firstName": "Robert",
"middleName": "James",
"lastName": "Johnson",
"title": "Dr.",
"suffix": "PhD"
}
Pattern:
{
"fullName": "firstName + lastName",
"formalName": "title + firstName + middleName + lastName + suffix",
"displayName": "firstName + middleName + lastName"
}
Expected Result:
{
"fullName": "Robert Johnson",
"formalName": "Dr. Robert James Johnson PhD",
"displayName": "Robert James Johnson"
}
Important Notes on Field Combination:
- Fields are joined with a single space separator
- Empty, null, or whitespace-only fields are automatically skipped
- Internal whitespace, newlines, and special characters are preserved
- Only leading and trailing spaces/tabs are trimmed from each field value
- Newlines (
\n,\r\n) within field values are preserved - Supports complex values like XML tags, multilingual text, and formatted strings
Complex Value Example:
{
"name": "<km-KH>សៀវនី</km-KH>\n<en-US></en-US>",
"code": "001"
}
Pattern:
{
"nameCode": "name + code"
}
Result:
{
"nameCode": "<km-KH>សៀវនី</km-KH>\n<en-US></en-US> 001"
}
The newlines and XML-like tags are preserved in the combined output.
Wildcard Usage
Example 4: Preserve Entire Object
Source JSON:
{
"id": "user_123",
"name": "Alice Cooper",
"email": "alice@example.com",
"metadata": {
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-11-23T14:45:00Z",
"version": 2
}
}
Pattern:
{
"userId": "id",
"userName": "name",
"original": "*"
}
Expected Result:
{
"userId": "user_123",
"userName": "Alice Cooper",
"original": {
"id": "user_123",
"name": "Alice Cooper",
"email": "alice@example.com",
"metadata": {
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-11-23T14:45:00Z",
"version": 2
}
}
}
Array Element Mapping
Example 5: Simple Flat Array Mapping
Source JSON:
[
{
"orderId": "ORD001",
"customerName": "Alice",
"status": "completed",
"total": 150.50
},
{
"orderId": "ORD002",
"customerName": "Bob",
"status": "pending",
"total": 200.00
},
{
"orderId": "ORD003",
"customerName": "Charlie",
"status": "completed",
"total": 75.25
}
]
Pattern:
{
"@array": "$[*]",
"@map": {
"id": "orderId",
"customer": "customerName",
"orderStatus": "status",
"amount": "total:decimal"
}
}
Expected Result:
[
{
"id": "ORD001",
"customer": "Alice",
"orderStatus": "completed",
"amount": 150.50
},
{
"id": "ORD002",
"customer": "Bob",
"orderStatus": "pending",
"amount": 200.00
},
{
"id": "ORD003",
"customer": "Charlie",
"orderStatus": "completed",
"amount": 75.25
}
]
Note: When the source JSON is already a flat array at the root level, use $[*] as the array path to reference all elements.
Example 6: Transform Array Elements with Field Mapping (Nested)
Source JSON:
{
"data": {
"users": [
{
"id": 1,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"isActive": true
},
{
"id": 2,
"firstName": "Jane",
"lastName": "Smith",
"email": "jane@example.com",
"isActive": false
},
{
"id": 3,
"firstName": "Bob",
"lastName": "Wilson",
"email": "bob@example.com",
"isActive": true
}
]
}
}
Pattern:
{
"@array": "data.users[*]",
"@map": {
"userId": "id",
"fullName": "firstName + lastName",
"contactEmail": "email",
"status": "isActive"
}
}
Expected Result:
[
{
"userId": 1,
"fullName": "John Doe",
"contactEmail": "john@example.com",
"status": true
},
{
"userId": 2,
"fullName": "Jane Smith",
"contactEmail": "jane@example.com",
"status": false
},
{
"userId": 3,
"fullName": "Bob Wilson",
"contactEmail": "bob@example.com",
"status": true
}
]
Type Casting
Example 6: Type Conversion in Array Mapping
Source JSON:
{
"products": [
{
"productId": 101,
"productName": "Laptop",
"price": 999.99,
"quantity": 5,
"inStock": true,
"tags": ["electronics", "computers"]
},
{
"productId": 102,
"productName": "Mouse",
"price": 29.99,
"quantity": 50,
"inStock": true,
"tags": ["electronics", "accessories"]
}
]
}
Pattern:
{
"@array": "products[*]",
"@map": {
"id": "productId:string",
"name": "productName",
"priceInt": "price:int",
"priceDecimal": "price:decimal",
"qty": "quantity:int",
"available": "inStock:bool",
"displayName": "productName + productId:string"
}
}
Expected Result:
[
{
"id": "101",
"name": "Laptop",
"priceInt": 999,
"priceDecimal": 999.99,
"qty": 5,
"available": true,
"displayName": "Laptop 101"
},
{
"id": "102",
"name": "Mouse",
"priceInt": 29,
"priceDecimal": 29.99,
"qty": 50,
"available": true,
"displayName": "Mouse 102"
}
]
Complex Transformations
Example 7: Nested Object with Array Mapping
Source JSON:
{
"company": {
"name": "Tech Corp",
"location": "San Francisco",
"employees": [
{
"empId": "E001",
"firstName": "Sarah",
"lastName": "Johnson",
"department": "Engineering",
"salary": 120000,
"skills": ["Python", "Java", "Docker"]
},
{
"empId": "E002",
"firstName": "Michael",
"lastName": "Brown",
"department": "Marketing",
"salary": 85000,
"skills": ["SEO", "Content Writing", "Analytics"]
}
]
}
}
Pattern:
{
"companyName": "company.name",
"office": "company.location",
"staff": {
"@array": "company.employees[*]",
"@map": {
"employeeId": "empId",
"fullName": "firstName + lastName",
"dept": "department",
"annualSalary": "salary:decimal",
"monthlySalary": "salary:decimal",
"originalData": "*"
}
}
}
Expected Result:
{
"companyName": "Tech Corp",
"office": "San Francisco",
"staff": [
{
"employeeId": "E001",
"fullName": "Sarah Johnson",
"dept": "Engineering",
"annualSalary": 120000.0,
"monthlySalary": 120000.0,
"originalData": {
"empId": "E001",
"firstName": "Sarah",
"lastName": "Johnson",
"department": "Engineering",
"salary": 120000,
"skills": ["Python", "Java", "Docker"]
}
},
{
"employeeId": "E002",
"fullName": "Michael Brown",
"dept": "Marketing",
"annualSalary": 85000.0,
"monthlySalary": 85000.0,
"originalData": {
"empId": "E002",
"firstName": "Michael",
"lastName": "Brown",
"department": "Marketing",
"salary": 85000,
"skills": ["SEO", "Content Writing", "Analytics"]
}
}
]
}
FormData Field Extraction
Example 9: Extract Field Value from FormData Array
This example demonstrates how to filter through a fieldDatas array to find a specific field by its fieldKey and extract nested data values.
Source JSON:
{
"formData": {
"id": "form_12345",
"fieldDatas": [
{
"id": "field_001",
"fieldKey": "FirstName",
"data": {
"value": "John",
"displayValue": "John"
}
},
{
"id": "field_002",
"fieldKey": "LicenseSelect",
"data": {
"value": "DL-2024-ABC123",
"displayValue": "Driver's License: DL-2024-ABC123",
"metadata": {
"issueDate": "2024-01-15",
"expiryDate": "2029-01-15"
}
}
},
{
"id": "field_003",
"fieldKey": "Email",
"data": {
"value": "john@example.com",
"displayValue": "john@example.com"
}
}
]
}
}
Pattern:
{
"license_id": "formData.fieldDatas[?(@.fieldKey == 'LicenseSelect')].data.value"
}
Expected Result:
{
"license_id": "DL-2024-ABC123"
}
Alternative Pattern (Multiple Fields):
{
"license_id": "formData.fieldDatas[?(@.fieldKey == 'LicenseSelect')].data.value",
"license_display": "formData.fieldDatas[?(@.fieldKey == 'LicenseSelect')].data.displayValue",
"license_metadata": "formData.fieldDatas[?(@.fieldKey == 'LicenseSelect')].data.metadata",
"first_name": "formData.fieldDatas[?(@.fieldKey == 'FirstName')].data.value",
"email": "formData.fieldDatas[?(@.fieldKey == 'Email')].data.value"
}
Alternative Pattern Result:
{
"license_id": "DL-2024-ABC123",
"license_display": "Driver's License: DL-2024-ABC123",
"license_metadata": {
"issueDate": "2024-01-15",
"expiryDate": "2029-01-15"
},
"first_name": "John",
"email": "john@example.com"
}
Pattern with Type Casting:
{
"license_id": "formData.fieldDatas[?(@.fieldKey == 'LicenseSelect')].data.value:string",
"license_id_display": "formData.fieldDatas[?(@.fieldKey == 'LicenseSelect')].data.value",
"first_name_upper": "formData.fieldDatas[?(@.fieldKey == 'FirstName')].data.value:string"
}
Type Casting Result:
{
"license_id": "DL-2024-ABC123",
"license_id_display": "DL-2024-ABC123",
"first_name_upper": "John"
}
Use Case: This pattern is commonly used when working with dynamic form data where fields are stored in an array structure with keys and nested data objects. It allows you to extract specific field values by filtering on the fieldKey property. Type casting can be applied directly to the JSONPath expression using the :type syntax.
JSONPath Filter Expressions with Type Casting
Example 10: Extract and Cast Field Values from FormData Array
This example demonstrates type casting combined with JSONPath filter expressions to extract and transform field values.
Source JSON:
{
"formSubmission": {
"id": "sub_789",
"fieldDatas": [
{
"id": "field_001",
"fieldKey": "age",
"data": {
"value": "25",
"displayValue": "25 years old"
}
},
{
"id": "field_002",
"fieldKey": "salary",
"data": {
"value": "75000.50",
"displayValue": "$75,000.50"
}
},
{
"id": "field_003",
"fieldKey": "isActive",
"data": {
"value": "true",
"displayValue": "Active"
}
},
{
"id": "field_004",
"fieldKey": "employeeId",
"data": {
"value": 12345,
"displayValue": "EMP-12345"
}
}
]
}
}
Pattern:
{
"age_int": "formSubmission.fieldDatas[?(@.fieldKey == 'age')].data.value:int",
"age_string": "formSubmission.fieldDatas[?(@.fieldKey == 'age')].data.value:string",
"salary_decimal": "formSubmission.fieldDatas[?(@.fieldKey == 'salary')].data.value:decimal",
"salary_int": "formSubmission.fieldDatas[?(@.fieldKey == 'salary')].data.value:int",
"is_active_bool": "formSubmission.fieldDatas[?(@.fieldKey == 'isActive')].data.value:bool",
"employee_id_string": "formSubmission.fieldDatas[?(@.fieldKey == 'employeeId')].data.value:string",
"employee_id_raw": "formSubmission.fieldDatas[?(@.fieldKey == 'employeeId')].data.value"
}
Expected Result:
{
"age_int": 25,
"age_string": "25",
"salary_decimal": 75000.50,
"salary_int": 75000,
"is_active_bool": true,
"employee_id_string": "12345",
"employee_id_raw": 12345
}
Supported Type Casts with JSONPath Filters:
:stringor:str- Convert to string:intor:integer- Convert to 32-bit integer:longor:int64- Convert to 64-bit integer:decimal- Convert to decimal (high precision):double- Convert to double-precision float:float- Convert to single-precision float:boolor:boolean- Convert to boolean:date- Convert to date (time component removed):datetime- Convert to full datetime
Use Case: This pattern is useful when extracting form field values that need to be transformed to specific data types for API integration, database storage, or business logic processing. The type casting ensures that string representations of numbers, booleans, or dates are properly converted to their native types.
Example 8: Nested Object Mapping with Literal Values
This example demonstrates using nested object patterns within @map to create structured field metadata objects. The @literal:value syntax outputs literal strings without extracting from source data.
Source JSON:
[
{
"name": "Chenda da",
"numberOfShares": 20,
"from": 10,
"to": 20,
"startDate": "2025-11-29T00:00:00+07:00",
"note": "First shareholder"
},
{
"name": "រឹម ចំរើន",
"numberOfShares": 10,
"from": 1,
"to": 10,
"startDate": "2025-11-29T00:00:00+07:00",
"note": null
}
]
Pattern:
{
"@array": "$[*]",
"@map": {
"name": {
"fieldKey": "@literal:name",
"data": "name"
},
"numberOfShares": {
"fieldKey": "@literal:numberOfShares",
"data": "numberOfShares:int"
},
"from": {
"fieldKey": "@literal:from",
"data": "from:int"
},
"to": {
"fieldKey": "@literal:to",
"data": "to:int"
},
"startDate": {
"fieldKey": "@literal:startDate",
"data": "startDate:datetime"
},
"note": {
"fieldKey": "@literal:note",
"data": "note"
}
}
}
Expected Result:
[
{
"name": {
"fieldKey": "name",
"data": "Chenda da"
},
"numberOfShares": {
"fieldKey": "numberOfShares",
"data": 20
},
"from": {
"fieldKey": "from",
"data": 10
},
"to": {
"fieldKey": "to",
"data": 20
},
"startDate": {
"fieldKey": "startDate",
"data": "2025-11-29T00:00:00"
},
"note": {
"fieldKey": "note",
"data": "First shareholder"
}
},
{
"name": {
"fieldKey": "name",
"data": "រឹម ចំរើន"
},
"numberOfShares": {
"fieldKey": "numberOfShares",
"data": 10
},
"from": {
"fieldKey": "from",
"data": 1
},
"to": {
"fieldKey": "to",
"data": 10
},
"startDate": {
"fieldKey": "startDate",
"data": "2025-11-29T00:00:00"
},
"note": {
"fieldKey": "note",
"data": null
}
}
]
Use Case: This pattern is useful when transforming data for dynamic form systems where each field needs metadata (like fieldKey, fieldType, label, etc.) alongside the actual data value. The @literal: prefix allows you to output static strings as values, while nested objects enable rich structured transformations.
Edge Cases
Source JSON:
{
"orders": [
{
"orderId": "ORD001",
"customerName": "Alice",
"status": "completed",
"total": 150.50
},
{
"orderId": "ORD002",
"customerName": "Bob",
"status": "pending",
"total": 200.00
},
{
"orderId": "ORD003",
"customerName": "Charlie",
"status": "completed",
"total": 75.25
}
]
}
Pattern:
{
"completedOrder": "orders[?(@.status == 'completed')].orderId",
"pendingCustomer": "orders[?(@.status == 'pending')].customerName",
"completedTotal": "orders[?(@.status == 'completed')].total"
}
Expected Result:
{
"completedOrder": "ORD001",
"pendingCustomer": "Bob",
"completedTotal": 150.50
}
Edge Cases
Example 11: Null and Missing Values
Source JSON:
{
"user": {
"id": 123,
"name": "Test User",
"email": null,
"phone": ""
}
}
Pattern:
{
"userId": "user.id",
"userName": "user.name",
"contact": "user.email",
"phoneNumber": "user.phone",
"missingField": "user.address",
"fullInfo": "user.name + user.email + user.phone"
}
Expected Result:
{
"userId": 123,
"userName": "Test User",
"contact": null,
"phoneNumber": "",
"missingField": null,
"fullInfo": "Test User"
}
Example 12: Case-Insensitive Property Matching
Source JSON:
{
"FirstName": "Emma",
"lastName": "Watson",
"EMAIL": "emma@example.com",
"PhoneNumber": "+44-7700-900000"
}
Pattern (with ignoreCase=true):
{
"name": "firstname + lastname",
"email": "email",
"phone": "phonenumber"
}
Expected Result:
{
"name": "Emma Watson",
"email": "emma@example.com",
"phone": "+44-7700-900000"
}
Notes
- Case Sensitivity: Set
ignoreCase=truefor case-insensitive property matching - Performance: Complex nested transformations may impact performance with large datasets
- Error Handling: Invalid paths return
null, invalid type casts returnnull - JSONPath Filters: Supports simple equality filters (
==,!=) with type casting support (e.g.,path[?(@.key == 'value')].field:int) - Field Combination: Empty or null fields are skipped in combination
- Type Casting: Can be applied to any string pattern including JSONPath filters using
:typesyntax - Array Mapping: Use
@arrayand@mapfor transforming array elements with field mapping - Nested Objects:
@mapsupports nested object patterns for creating structured transformations - Literal Values: Use
@literal:valuesyntax to output literal strings instead of extracting from source data