remarshal

repository·master·Indexed 19 days ago

https://github.com/remarshal-project/remarshal

A tool and Python library for converting between CBOR, JSON, MessagePack, TOML, and YAML serialization formats, as well as converting these formats into Python code. It supports lossless conversion, Starlark-based data transformations, and specific handling for YAML versions 1.1 and 1.2.

Tokens
10.3K
Snippets
39
Records
46
Agent score
68%

What's inside remarshal

  1. How to use Remarshal as a Python library

    master

    While Remarshal is primarily a CLI application, it can be used as a Python library. Because the library usage is not as strictly governed as the CLI, it is recommended to pin your dependency to a specific minor version to avoid breaking changes in the Python API during minor updates.

    Example dependency constraint: remarshal>=2.1,<2.2

    Note that dropping support for old Python versions is not considered a breaking change and will not trigger a major version bump.

    # In your requirements.txt or pyproject.toml
    remarshal>=2.1,<2.2
  2. Understand date-time and binary conversion limitations

    master

    Remarshal has specific constraints regarding data types during conversion:

    Binary Fields

    • JSON and TOML: Cannot accept binary fields. Therefore, CBOR, MessagePack, or YAML containing binary fields cannot be converted to JSON or TOML.
    • CBOR, MessagePack, and YAML: These formats can be converted between each other while preserving binary fields.

    Date-time Conversions

    • Local Dates: Can be converted between CBOR RFC 8943 (tag 1004), TOML Local Dates, and YAML timestamps (without time or timezone).
    • Local Date-Time: Can be converted between TOML Local Date-Time and YAML timestamps (without timezone).
    • Date-time with Timezone: Can be converted between CBOR standard date-time strings (tag 0), MessagePack Timestamp extension type, TOML Offset Date-Times, and YAML timestamps (with timezone).
    • TOML Local Time: Cannot be converted to a date-time in any other format.
    • JSON Requirement: To convert any date-time type to JSON, you must use the -k/--stringify option to convert them to strings.
  3. Handle YAML tags using --yaml-tags

    master

    YAML tags (e.g., !secret) are not natively supported by other formats like JSON. By default, Remarshal errors when encountering tags.

    Using --yaml-tags allows you to represent a tag as a single-key mapping where the key starts with !. This enables round-tripping tags through formats that don't support them.

    Example: Converting tagged YAML to JSON

    $ printf 'name: !secret pw\nport: 8123\n' | remarshal --from yaml --to json --yaml-tags
    {"name":{"!secret":"pw"},"port":8123}
    $ echo '{"!my-tag": {"foo": "bar", "baz": 123}}' \
      | remarshal --from json --to yaml --yaml-tags
    !my-tag
    foo: bar
    baz: 123
  4. Wrap and unwrap data for TOML compatibility

    master

    TOML requires the top-level element to be a dictionary (map). If your input data (from JSON, CBOR, etc.) is a list or a primitive, conversion to TOML will fail.

    • --wrap <key>: Wraps the input data in a new dictionary where the input is the value associated with <key>.
    • --unwrap <key>: Extracts the value associated with <key> from the top-level dictionary and outputs only that value, discarding the rest.

    Example: Converting a JSON list to TOML

    # This fails:
    echo '[{"a":"b"}]' | remarshal --from json --to toml
    
    # This works by wrapping the list in a 'main' key:
    echo '[{"a":"b"}]' | remarshal --from json --to toml --wrap main
    $ echo '[{"a":"b"},{"c":[1,2,3]}]' \
      | remarshal --from json --to toml --wrap main
    [[main]]
    a = "b"
    
    [[main]]
    c = [1, 2, 3]
  5. Enable lossy conversion with --stringify

    master

    By default, Remarshal operates in lossless mode. It attempts to ensure that a document converted from format A to B and back to A remains identical to the original. If a lossless conversion is impossible, Remarshal will exit with an error.

    To relax this restriction and allow conversions that might lose type fidelity (by converting specific types to strings), use the -k or --stringify option. This is often necessary when converting to JSON or TOML.

    When --stringify is enabled:

    • JSON conversion: Boolean, null, and date-time keys/values are turned into strings.
    • TOML conversion: Boolean, date-time, and null keys/values are turned into strings.
    • Date-time to JSON: Converting documents with date-time types to JSON requires this option to turn them into strings.
    remarshal -k [args]
  6. Install Remarshal

    master

    Remarshal requires Python 3.12 or later. The recommended way to install it is using pipx or uv to ensure it is available as a standalone tool.

    To install the latest release:

    pipx install remarshal
    # or
    uv tool install remarshal

    You can also run Remarshal without a permanent installation using pipx run or uvx, which will download and cache the tool temporarily:

    pipx run remarshal [arg ...]
    # or
    uvx remarshal [arg ...]

    To install the current development version from GitHub:

    pipx install git+https://github.com/remarshal-project/remarshal
    # or
    uv tool install git+https://github.com/remarshal-project/remarshal
    pipx install remarshal
    # or
    uv tool install remarshal
  7. Use the Remarshal CLI to convert data formats

    master

    Remarshal is a CLI tool for converting between CBOR, JSON, MessagePack, TOML, and YAML. You can use the main remarshal command with explicit format flags or use short-hand commands like json2yaml or yaml2toml.

    Input/Output:

    • If no input file is provided or -i - is used, Remarshal reads from stdin.
    • If no output file is provided or -o - is used, Remarshal writes to stdout.

    Exit Codes:

    • 0: Success
    • 1: Operational failure
    • 2: Command line parsing failure
    # Using explicit flags
    remarshal -f json -t yaml input.json output.yaml
    
    # Using short-hand commands
    json2yaml input.json output.yaml
    
    # Using stdin/stdout
    echo '{"a": 1}' | json2yaml - > output.yaml
  8. Transform data with Starlark

    master

    Remarshal supports data transformations using Starlark, a sandboxed Python-like language.

    • Use --starlark <code_expression> for single expressions. The expression value becomes the new document.
    • Use --starlark-file <path> for full programs. The program must assign the output to the variable result.
    • The input data is available in the Starlark environment as the variable data.

    Type Mapping in Starlark:

    Remarshal TypeStarlark TypeNotes
    int, bool, float, strSame
    dictdictInsertion order is preserved
    listlist
    bytesOpaqueUse remarshal.bytes_to_str, remarshal.str_to_bytes, etc.
    Date/TimeOpaqueUse remarshal.datetime_to_iso, remarshal.iso_to_datetime, etc.

    Note: A set returned by Starlark will cause an error; convert it to a list or sorted() list first.

    Example: Filtering JSON users with Starlark

    $ echo '{"users":[{"name":"Alice","active":true},{"name":"Bob","active":false}]}' \
      | remarshal -f json -t yaml \
          --starlark '[user["name"] for user in data["users"] if user["active"]]'
    - Alice
    $ echo '{"a":1,"b":2,"c":3}' \
      | remarshal -f json -t json \
          --starlark 'x = sum(data.values()); result = {"sum": x, "values": data}'
    {"sum":6,"values":{"a":1,"b":2,"c":3}}
  9. Convert data to Python code

    master

    Remarshal can transform data into Python code. This is a one-way operation.

    Output Formats

    • Default: Uses Python's repr() format. Note that the default repr format ignores the -s/--sort-keys flag.
    • Formatted: Uses pprint.pformat when the --indent option is passed.

    Important Notes

    • Imports: The generated Python code does not include necessary import statements. For example, if your data contains date-times, you must manually add import datetime to your script.
    • Formatting: The pprint output style may not match your project's specific coding style; it is recommended to run a dedicated Python formatter (like Black or Ruff) on the output.
    remarshal --indent [input_file] > output.py
  10. Represent YAML tags with TaggedValue

    master

    In Remarshal, YAML tags (like !secret) are represented in-memory using the TaggedValue dataclass. This allows you to preserve tag information during transformations.

    When converting to formats that do not support native tags (like JSON), TaggedValue is typically converted into a single-key mapping envelope, e.g., {"!secret": "password"}. This behavior is controlled by the --yaml-tags option in the CLI.

    To convert a document containing TaggedValue objects into these mapping envelopes (useful before encoding to non-YAML formats), use tags_to_envelopes(). To convert these envelopes back into TaggedValue objects (useful before encoding to YAML), use envelopes_to_tags().

    from remarshal.document import TaggedValue
    
    tagged = TaggedValue(tag="!secret", value="password")
    # Represented as: TaggedValue(tag='!secret', value='password')
  11. Automatic registration of built-in codecs

    master

    Importing the remarshal.codecs package automatically registers all built-in codecs into the remarshal.codec registries (DECODERS and ENCODERS). This allows the core remarshal library to automatically discover and use these codecs when performing conversions between formats.

    import remarshal.codecs
    # All codecs are now registered and available via the remarshal registry.
  12. Configure YAML versions

    master

    Remarshal supports both YAML 1.1 and YAML 1.2. By default, it uses YAML 1.2. You can explicitly select the version using the following format identifiers:

    • yaml-1.1: Use YAML 1.1.
    • yaml-1.2: Use YAML 1.2 (default).

    Conversion between these two versions is supported.