Skip to main content

A JSON transformer engine that transforms JSON objects based on configurable mapping rules

Project description

JSON Transformer

A Python-based JSON transformation engine that can transform JSON objects based on configurable mapping rules.

Features

  • Transform any JSON object to a different structure using mapping configuration
  • Support for deep nested JSON objects, arrays, and complex hierarchies
  • Handle arrays, objects within arrays, and arrays within objects
  • Concatenate fields from different levels in the source JSON
  • Exclude missing fields from the output
  • Easy-to-understand mapping syntax
  • Command-line interface for quick transformations

Installation

  1. Clone the repository:
git clone https://github.com/rayhanhasnat/json-transformer.git
cd json-transformer
  1. Install the package:
pip install -e .

Or install directly from PyPI:

pip install json-mapping-transformer

Usage

Python API

Basic Usage

from json_transformer import transform_json

# Source JSON
source = {
    "name": "John Doe",
    "age": 30,
    "email": "john.doe@example.com"
}

# Mapping configuration
mapping = {
    "full_name": "name",
    "user_age": "age"
}

# Transform the JSON
result = transform_json(source, mapping)
print(result)
# Output: {"full_name": "John Doe", "user_age": 30}

Advanced Usage

Nested Object Mapping
source = {
    "user": {
        "personal": {
            "name": "John Doe",
            "age": 30
        },
        "contact": {
            "email": "john.doe@example.com",
            "phone": "555-1234"
        }
    },
    "company": "Acme Inc."
}

mapping = {
    "name": "user.personal.name",
    "contact_info": {
        "email": "user.contact.email",
        "phone": "user.contact.phone"
    },
    "employer": "company"
}

result = transform_json(source, mapping)
# Output:
# {
#     "name": "John Doe",
#     "contact_info": {
#         "email": "john.doe@example.com",
#         "phone": "555-1234"
#     },
#     "employer": "Acme Inc."
# }

If a nested object mapping (like contact_info above) results in an empty object (e.g., if both user.contact.email and user.contact.phone were missing or null in the source), the key for that empty object (contact_info) will be omitted from the output.

Array Mapping
source = {
    "user": "John Doe",
    "items": [
        {"id": 1, "name": "Item 1", "price": 10.99},
        {"id": 2, "name": "Item 2", "price": 20.50},
        {"id": 3, "name": "Item 3", "price": 5.75}
    ]
}

mapping = {
    "customer": "user",
    "products": {
        "_map": "items",
        "_src": {
            "product_id": "id",
            "product_name": "name",
            "cost": "price"
        }
    }
}

result = transform_json(source, mapping)
# Output:
# {
#     "customer": "John Doe",
#     "products": [
#         {"product_id": 1, "product_name": "Item 1", "cost": 10.99},
#         {"product_id": 2, "product_name": "Item 2", "cost": 20.50},
#         {"product_id": 3, "product_name": "Item 3", "cost": 5.75}
#     ]
# }

When mapping to an array of objects (like products):

  1. Each item in the source array is transformed according to its _src mapping.
  2. If any transformed item results in an empty object ({}), it is removed from the list.
  3. If, after this filtering, the entire list of objects becomes empty (or if the source array was initially empty, or all items mapped to null primitives that were filtered out), the target key for the array (products) will be omitted from the output.
Array of Objects to Array of Primitives

Map an array of objects to an array of primitive values (e.g., strings, numbers) by specifying the field to extract from each object. If the extracted value from an object is null (or None), it will be excluded from the resulting array. If, after processing all objects and excluding null values, the resulting array of primitives is empty, the entire target key for this array (e.g., contact_numbers) will be omitted from the output.

source = {
    "name": "John Doe",
    "contacts": [
        {"type": "phone", "text": "111111"},
        {"type": "email", "text": None},
        {"type": "mobile", "text": "222222"},
        {"type": "emergency", "text": "333333"}
    ]
}

mapping = {
    "name": "name",
    "contact_numbers": {
        "_map": "contacts",
        "_src": "text"
    }
}

result = transform_json(source, mapping)
# Output:
# {
#     "name": "John Doe",
#     "contact_numbers": ["111111", "222222", "333333"]
# }
Value Collection

Collect values from multiple sources into a single array. The _args parameter can include:

  • Direct paths to values (strings)
  • Array sources with field extraction (objects with _map configuration)
source = {
    "user": {
        "name": "John Doe",
        "contacts": [
            {"type": "phone", "number": "111111"},
            {"type": "email", "address": "john@example.com"}
        ]
    },
    "company": {
        "name": "Acme Inc",
        "departments": [
            {"name": "IT", "code": "D001"},
            {"name": "HR", "code": "D002"}
        ]
    }
}

mapping = {
    "collected_info": {
        "_type": "collect",
        "_args": [
            "user.name",
            {
                "_map": "user.contacts",
                "_src": "number"
            },
            {
                "_map": "company.departments",
                "_src": "code"
            }
        ]
    }
}

result = transform_json(source, mapping)
# Output:
# {
#     "collected_info": ["John Doe", "111111", "D001", "D002"]
# }
Field Concatenation

Concatenate multiple fields from the source JSON into a single field in the output. You can use both field paths and literal values in the concatenation.

source = {
    "user": {
        "firstName": "John",
        "lastName": "Doe",
        "title": "Mr"
    },
    "address": {
        "street": "123 Main St",
        "city": "Boston",
        "state": "MA",
        "zip": "02108"
    }
}

mapping = {
    "full_name": {
        "_type": "concat",
        "_args": ["user.title", " ", "user.firstName", " ", "user.lastName"]
    },
    "full_address": {
        "_type": "concat",
        "_args": [
            "address.street",
            ", ",
            "address.city",
            ", ",
            "address.state",
            ", ",
            "address.zip"
        ]
    }
}

result = transform_json(source, mapping)
# Output:
# {
#     "full_name": "Mr John Doe",
#     "full_address": "123 Main St, Boston, MA, 02108"
# }

The concatenation transformation supports:

  • Field paths (e.g., "user.firstName")
  • Literal values (e.g., " ")
  • Custom separators between values
  • Automatic skipping of null or empty values
First Available Value

Get the first available (non-null) value from multiple source fields. If none of the source fields have a value, the target field will be excluded from the output. This transformation can be used both at the root level and within array mappings.

Basic Usage
source = {
    "code": {
        "coding": [
            {
                "system": "http://www.nlm.nih.gov/research/umls/rxnorm",
                "code": "7980"
            }
        ],
        "text": "Penicillin Allergy"
    }
}

mapping = {
    "code": {
        "_type": "first",
        "_args": [
            "code.coding[0].display",  # This doesn't exist
            "code.text"                # This exists and will be used
        ]
    }
}

result = transform_json(source, mapping)
# Output:
# {
#     "code": "Penicillin Allergy"
# }
Using First Available Value in Arrays

You can use the first available value transformation within array mappings to extract the first non-null value for each array item.

source = {
    "manifestation": [
        {
            "coding": [
                {
                    "system": "http://snomed.info/sct",
                    "code": "39579001",
                    "display": "Anaphylaxis"
                }
            ],
            "text": "Anaphylactic shock"
        },
        {
            "coding": [
                {
                    "system": "http://snomed.info/sct",
                    "code": "247472004",
                    "display": "Hives"
                }
            ]
        }
    ]
}

mapping = {
    "manifestation": {
        "_map": "manifestation",
        "_src": {
            "_type": "first",
            "_args": ["text", "coding[0].display"]
        }
    }
}

result = transform_json(source, mapping)
# Output:
# {
#     "manifestation": ["Anaphylactic shock", "Hives"]
# }

In this example:

  1. For the first array item, it uses "text" ("Anaphylactic shock") since it exists
  2. For the second array item, since "text" doesn't exist, it falls back to "coding[0].display" ("Hives")
  3. If neither value exists for an item, that item will be excluded from the output array
Conditional Mapping

Map values based on conditions. The condition can use various operators to compare values.

source = {
    "age": 25,
    "status": "active"
}

mapping = {
    "age_category": {
        "_type": "conditional",
        "_args": {
            "condition": "age > 18",
            "true": "adult",
            "false": "minor"
        }
    },
    "access_level": {
        "_type": "conditional",
        "_args": {
            "condition": "status == active",
            "true": "full",
            "false": "restricted"
        }
    }
}

result = transform_json(source, mapping)
# Output:
# {
#     "age_category": "adult",
#     "access_level": "full"
# }

Command Line Interface

The package includes a command-line interface for transforming JSON files:

# Basic usage
json-transform source.json mapping.json output.json

# Pretty print the output
json-transform source.json mapping.json output.json --pretty

# Show verbose output
json-transform source.json mapping.json output.json --verbose

# Get help
json-transform --help

CLI Options

  • --pretty: Pretty print the output JSON
  • --verbose: Show detailed transformation information
  • --help: Show help message

Special Fields

  • _map: Specifies array mapping
  • _src: Defines source mapping for arrays
  • _type: Specifies transformation type
  • _args: Provides arguments for transformations

Transformation Types

  1. concat: Concatenate multiple values
  2. collect: Collect values from arrays
  3. first: Get first available value
  4. conditional: Map based on conditions

Condition Operators

  • >: Greater than
  • >=: Greater than or equal
  • <: Less than
  • <=: Less than or equal
  • ==: Equal to
  • !=: Not equal to

Error Handling

  • Missing fields return null
  • Invalid paths are ignored
  • Invalid transformations return null
  • Array index out of bounds returns null

Complex Example

{
    "profile": {
        "name": {
            "_type": "concat",
            "_args": ["user.first_name", " ", "user.last_name"]
        },
        "contact": {
            "email": "user.email",
            "phone": "user.phone"
        },
        "address": {
            "_type": "concat",
            "_args": [
                "user.address.street",
                ", ",
                "user.address.city",
                ", ",
                "user.address.state"
            ]
        }
    },
    "orders": {
        "_map": "user.orders",
        "_src": {
            "order_id": "id",
            "items": {
                "_map": "items",
                "_src": {
                    "name": "product.name",
                    "quantity": "quantity"
                }
            }
        }
    }
}

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Commit your changes
  4. Push to the branch
  5. Create a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

json_mapping_transformer-0.1.1.tar.gz (9.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

json_mapping_transformer-0.1.1-py3-none-any.whl (9.7 kB view details)

Uploaded Python 3

File details

Details for the file json_mapping_transformer-0.1.1.tar.gz.

File metadata

File hashes

Hashes for json_mapping_transformer-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a7f5b68aee7617e3075a69e7eaef7887ebbbdaed5bd0ef09af1f2fa8f4159dea
MD5 3822f054cbbf5dbe966e694a0c94e8e0
BLAKE2b-256 ad8d2939e3f03eea3b8162af2fba5d5d43fae100b8baa0a705ff325dbc771948

See more details on using hashes here.

File details

Details for the file json_mapping_transformer-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for json_mapping_transformer-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 80618c86d9ddb690ec721bf219cce19af3b8749956e14b3d2a7de1ccf40ffc55
MD5 c53264eef68eea3fd624ff17970370db
BLAKE2b-256 ebac961a1ad15f8657cfa0d7930ecc6dcfa445d4a850ca0bd6df01d4511bb378

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page