|
#!/usr/bin/env python |
|
|
|
# The MIT License (MIT) |
|
|
|
# Copyright (c) 2015 Ben Kehoe |
|
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
|
# of this software and associated documentation files (the "Software"), to deal |
|
# in the Software without restriction, including without limitation the rights |
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
# copies of the Software, and to permit persons to whom the Software is |
|
# furnished to do so, subject to the following conditions: |
|
|
|
# The above copyright notice and this permission notice shall be included in |
|
# all copies or substantial portions of the Software. |
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
# THE SOFTWARE. |
|
|
|
# Updates at https://gist.github.com/benkehoe/7b6df9613d2a0bb5d434 |
|
|
|
import sys |
|
import yaml |
|
import yaml.constructor as yamlc |
|
import json |
|
import optparse |
|
|
|
yamlc.SafeConstructor.add_constructor(u'tag:yaml.org,2002:timestamp', yamlc.SafeConstructor.construct_yaml_str) |
|
|
|
def construct_yaml_set(self, node): |
|
data = [] |
|
yield data |
|
value = self.construct_mapping(node) |
|
data.extend(value.keys()) |
|
|
|
yamlc.SafeConstructor.add_constructor(u'tag:yaml.org,2002:set', construct_yaml_set) |
|
|
|
usage = """Usage: %prog [--pretty] INPUT_FILE [OUTPUT_FILE] |
|
%prog [--pretty] [--input INPUT_FILE] [--output OUTPUT_FILE] |
|
|
|
Convert YAML into JSON. With positional arguments, an input filename must |
|
be given. If no output file is given, the JSON will be sent to stdout. |
|
With named arguments, if --input is not given, the YAML will be read from |
|
stdin, and if --output is not given, the JSON will be written to stdout. |
|
The two standard YAML types not directly representable in JSON are timestamp |
|
and set. The exact string given in the YAML for a timestamp is stored in the |
|
JSON. Sets are converted to lists.""" |
|
|
|
parser = optparse.OptionParser(usage=usage) |
|
|
|
parser.add_option('-i', '--input', metavar='FILE') |
|
parser.add_option('-o', '--output', metavar='FILE') |
|
parser.add_option('-p', '--pretty', action='store_true', default=False, help='Pretty-print JSON for easier readability') |
|
|
|
options, args = parser.parse_args() |
|
|
|
if len(args) >= 3: |
|
parser.exit(1, 'Too many inputs!\n') |
|
|
|
if args and (options.input or options.output): |
|
parser.exit(1, "Can't specify both args and options\n") |
|
|
|
def open_file(name, mode): |
|
try: |
|
return open(name, mode, 1) |
|
except: |
|
parser.exit(2, "Could not open file %s\n" % name) |
|
|
|
if options.input: |
|
input = open_file(options.input,'r') |
|
elif len(args) >= 1: |
|
input = open_file(args[0],'r') |
|
else: |
|
input = sys.stdin |
|
|
|
if options.output: |
|
out = open_file(options.output,'w') |
|
elif len(args) == 2: |
|
out = open_file(args[1],'w') |
|
else: |
|
out = sys.stdout |
|
|
|
indent = 2 if options.pretty else None |
|
|
|
with input, out: |
|
try: |
|
value = yaml.safe_load(input) |
|
json.dump(value, out, indent=indent) |
|
out.write('\n') |
|
except: |
|
import traceback |
|
traceback.print_exception(*sys.exc_info()) |
|
sys.exit(3) |
|
sys.exit(0) |