go-plist

repository·main·Indexed 19 days ago

https://github.com/dhowett/go-plist

A pure Go library for transcoding Apple property lists (plists), supporting XML, Binary, OpenStep, and GNUStep formats. It allows encoding and decoding between these formats and arbitrary Go types. The package includes the `ply` command-line tool for converting plists to other formats like JSON and YAML, as well as extracting specific values using keypaths.

Tokens
4.1K
Snippets
19
Records
26
Agent score
66%

What's inside go-plist

  1. Overview of go-plist features

    main

    The go-plist library is a pure Go transcoder that supports encoding and decoding property lists. It handles multiple formats including:

    • Apple XML
    • Apple Binary
    • OpenStep
    • GNUStep

    It allows for seamless conversion between these formats and arbitrary Go types.

  2. Evaluate keypaths in Ply

    main

    Keypaths allow you to navigate and extract data from a property list. Keypaths are composed of several types of expressions:

    • /name: Accesses a dictionary key named name.
    • [i]: Accesses index i of an array, string, or data object.
    • [i:j]: Slices an array, string, or data object in the range [i, j).
    • !: Parses the current data value as a property list, making it the new base for further evaluation.
    • $(subexpression): Evaluates the subexpression and pastes its value into the path.

    Examples

    Given a plist with a dictionary a containing b which contains c (an array) and d (a string):

    # Access a dictionary key
    $ ply -k 'a/b/d' file.plist
    # Output: hello
    
    # Array indexing
    $ ply -k 'a/b/c[1]' file.plist
    # Output: 2
    
    # Array/Data slicing
    $ ply -k 'a/data[2:3]' file.plist
    
    # Subplist parsing (using !)
    # This treats the value at 'sub' as a new plist base
    $ ply -k 'sub!' file.plist
    
    # Subplist keypath evaluation
    $ ply -k 'sub!/this' file.plist
    
    # Subexpression evaluation
    $ ply -k '/$(/a/b/d)' file.plist
  3. Use the Ply CLI

    main

    Ply is a property list pretty-printer and converter. By default, it pretty-prints a plist to stdout. It can also be used to extract specific values using keypaths, convert plists to other formats, and subset plists into new files.

    # Basic pretty-print
    ply file.plist
    
    # Convert to JSON with indentation
    ply -c json -I file.plist
    
    # Extract a value using a keypath
    ply -k 'a/b/c' file.plist
  4. Convert and subset property lists with Ply

    main

    You can use Ply to extract a subset of a property list and save it to a new file in a different format. This is achieved by combining the -k (keypath), -c (convert), and -o (out) flags.

    Example: Extracting a sub-dictionary to an OpenStep file

    To extract the contents of /a/b from file.plist and save it as an indented OpenStep file named file-a-b.plist:

    ply -k '/a/b' -o file-a-b.plist -c openstep -I file.plist
  5. Configure struct field encoding with plist tags

    main

    When encoding structs, you can control how fields are serialized using the plist tag. The format is plist:"<key>[,flags...]".

    Supported flags:

    • omitempty: Only include the field if it is not the zero value for its type.
    • -: If the key is -, the field is ignored.

    Anonymous struct fields are treated as if their exported fields were part of the outer struct.

    type User struct {
        Name     string `plist:"name"` 
        Email    string `plist:"email,omitempty"` 
        Password string `plist:"-"` // Ignored
    }
  6. How Unmarshal handles different data types and formats

    main

    Type Mapping and Constraints

    • 128-bit Integers: Since Go lacks native 128-bit types, Unmarshal will drop the high 64 bits of any 128-bit integers found in binary property lists. This is intended behavior to handle CoreFoundation's serialization of large 64-bit values.
    • Interface Decoding: If decoding into a nil interface, Unmarshal allocates the appropriate concrete type (e.g., map[string]interface{} for dictionaries).
    • Type Mismatches: If a property list value is incompatible with the provided Go type, Unmarshal aborts and returns an error.

    OpenStep Format Behavior

    When an OpenStep property list is encountered, the decoder enters a relaxed parsing mode. Because OpenStep lists store everything as strings, the decoder attempts to recover types (integers, floats, booleans, dates) based on the target Go type. For example, if unmarshaling an OpenStep string into a time.Time, it will attempt to parse the string as a time.

  7. Extract values using keypaths in `ply`

    main

    You can use the --key flag to navigate through a property list and extract specific nested data. The keypath syntax supports several operations:

    • Maps: Use the key name (e.g., KeyName).
    • Arrays: Use square brackets with an index (e.g., [0]) or a slice (e.g., [0:2]).
    • Sub-plists: Use the ! operator to treat a data blob (byte array) as a nested property list (e.g., DataKey!).
    • Dynamic Expressions: Use $(...) to evaluate a subexpression (e.g., $(some_key)).

    You can also use the filename:keypath syntax as a shorthand for the --key flag.

    Example usage:

    # Extract the first element of an array named 'Items'
    ply --key Items[0] input.plist
    
    # Extract a nested key using the filename shorthand
    ply input.plist:NestedKey/SubKey
    ply --key "Key/SubKey[0]" input.plist
  8. Use the `ply` CLI to convert property lists

    main

    The ply command-line tool allows you to transcode property list files between various formats (XML, Binary, OpenStep, GNUStep) or convert them to other data formats like JSON and YAML. You can also use it to extract specific values from a plist using a keypath.

    To see all supported output formats, run the command with the --convert list flag.

    ply --convert <format> <filename>
    # Example: Convert a binary plist to JSON
    ply --convert json my_file.plist
    
    # Example: Convert a plist to an indented XML file
    ply --convert xml --indent --out output.xml input.plist
  9. Encode Go types to a property list

    main

    To encode arbitrary Go types (such as maps, structs, or slices) into a property list format, create a new encoder using plist.NewEncoder(io.Writer) and call the Encode method. The encoder writes the resulting property list to the provided writer.

    package main
    import (
    	"howett.net/plist"
    	"os"
    )
    func main() {
    	encoder := plist.NewEncoder(os.Stdout)
    	encoder.Encode(map[string]string{"hello": "world"})
    }
  10. Reference Ply CLI options

    main

    The following options are available for the ply command:

    FlagLong FlagDescription
    -c--convert=<format>Convert the property list to a new format. Supported formats: bplist, xml, gnustep (or gs), openstep (or os), json, yaml. Use list to list all supported formats.
    -k--key=<keypath>A keypath used to evaluate and extract a specific part of the plist.
    -o--out=<filename>Specify an output filename. If not provided, Ply will overwrite the input file (unless outputting to stdout via a pipe).
    -I--indentIndent output for formats that support it (xml, openstep, gnustep, json).
    -h--helpShow this help message.