User Rating 0.0
Total Usage 0 times
JSON Input
Plist Output
Is this tool helpful?

Your feedback helps us improve.

About

Apple Property List (plist) files are the standard configuration format across macOS, iOS, watchOS, and tvOS. They store serialized objects as XML conforming to Apple's DTD at https://www.apple.com/DTDs/PropertyList-1.0.dtd. Misconfigured plist files cause silent failures in Xcode builds, broken app preferences, and rejected App Store submissions. This converter performs a recursive type-mapped translation from JSON to plist XML 1.0, handling all 8 plist data types: dict, array, string, integer, real, boolean, date (ISO 8601), and data (Base64). It detects circular references and validates input before conversion.

The tool approximates type inference since JSON lacks plist's type granularity. Integers vs. reals are distinguished by the absence or presence of a decimal component. ISO 8601 strings matching the pattern YYYY-MM-DDTHH:mm:ssZ are auto-detected as date types. Base64-encoded strings are not auto-detected as data to avoid false positives. Pro Tip: if your JSON contains keys with periods (e.g., com.apple.security), they are preserved verbatim in the plist output since dots are valid in plist dictionary keys.

json to plist plist converter property list apple plist xml plist json converter ios plist macos plist

Formulas

The converter applies a recursive type-mapping function T that transforms each JSON node into its plist XML equivalent:

T(node) =
{
<string> if typeof node = "string" ¬isISO8601(node)<date> if typeof node = "string" isISO8601(node)<integer> if typeof node = "number" Number.isInteger(node)<real> if typeof node = "number" ¬Number.isInteger(node)<true/> or <false/> if typeof node = "boolean"<dict> if isObject(node)<array> if Array.isArray(node)<string/> if node = null

The ISO 8601 date detection uses the pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2} followed by an optional timezone designator. XML special characters are escaped via the mapping: & &, < <, > >, " ", ' '.

Where T = type mapping function, node = current JSON value being processed, isISO8601 = regex-based date string detector, isObject = plain object check excluding arrays and null.

Reference Data

JSON TypePlist TypePlist XML TagExample JSONExample Plist OutputNotes
Stringstring<string>"hello"<string>hello</string>XML entities escaped
Integer Numberinteger<integer>42<integer>42</integer>No decimal point
Float Numberreal<real>3.14<real>3.14</real>Has decimal component
Boolean truetrue<true/>true<true/>Self-closing tag
Boolean falsefalse<false/>false<false/>Self-closing tag
nullstring (empty)<string/>null<string/>No native null in plist
Objectdict<dict>{"a":1}<dict><key>a</key><integer>1</integer></dict>Keys become <key> tags
Arrayarray<array>[1,2]<array><integer>1</integer><integer>2</integer></array>Ordered collection
ISO 8601 Stringdate<date>"2024-01-15T08:30:00Z"<date>2024-01-15T08:30:00Z</date>Auto-detected pattern
Nested ObjectNested dict<dict>{"a":{"b":1}}Recursive conversionUnlimited depth
Mixed ArrayMixed array<array>[1,"a",true]Each element typed individuallyHeterogeneous support
Empty ObjectEmpty dict<dict/>{}<dict/>Self-closing
Empty ArrayEmpty array<array/>[]<array/>Self-closing
Large Integerinteger<integer>9007199254740991<integer>9007199254740991</integer>Max safe integer
Negative Numberinteger/real<integer> or <real>−7<integer>-7</integer>Sign preserved
Scientific Notationreal<real>1.5e10<real>15000000000</real>Expanded to decimal

Frequently Asked Questions

JSON has a single "number" type. The converter uses Number.isInteger() to differentiate. A value of 42 maps to 42, while 42.0 in JSON is technically indistinguishable from 42 after parsing (JavaScript treats both as the same number). If you need a value treated as , ensure it has a non-zero fractional part (e.g., 42.1) or manually edit the output. Values in scientific notation like 1.5e10 are expanded to their full decimal representation.
Apple's plist DTD defines no null or nil type. The converter maps JSON null to an empty tag, which is the most common convention used by Apple's own NSPropertyListSerialization when encountering NSNull. Some developers prefer to omit null keys entirely. You can remove these entries from your JSON before conversion if that behavior is preferred.
Yes. The converter maintains a visited-set during recursive traversal. If a circular reference is detected, the conversion halts immediately and displays an error message identifying the problematic path. Standard JSON.parse() cannot produce circular references, but programmatically constructed objects passed to the serializer could. The depth limit is set to 64 levels to prevent stack overflow on deeply nested structures.
Strings matching the regex pattern ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2} are auto-detected as plist types. This covers formats like 2024-01-15T08:30:00Z and 2024-01-15T08:30:00+05:00. The converter provides a toggle to disable auto-detection, treating all strings as plain types. This is useful when your JSON contains date-like strings that should remain as text.
The output conforms to Apple's PropertyList-1.0 DTD with the correct XML declaration () and DOCTYPE. It passes plutil -lint validation. The encoding is UTF-8 as required by the DTD. Key ordering within follows the insertion order from the source JSON, which matches how NSJSONSerialization preserves ordering on Apple platforms.
The converter accepts inputs up to 10 MB. Beyond that threshold, browser memory constraints may cause performance degradation or crashes. For files exceeding this limit, consider using command-line tools like plutil or Python's plistlib module. The converter processes the entire input synchronously, so very large nested structures (depth > 64 or arrays with > 100,000 elements) may trigger timeout warnings.