json格式字符串与xml格式互转

话不多说,直接上代码,没有注释!

1、xml解析代码

import copy
import re


class TinyXmlPraser:
    def __init__(self):
        self.version = ''
        self.nlist = []
        self.root = None
        self.node = None
         
    def from_file(self, xmlpath):
        filestr = self.filetostr(xmlpath)
        self.nlist = self.strtolist(filestr)
        self.ana_xml(self.nlist)
        return self.root
     
    def from_str(self,filestr):
        self.nlist = self.strtolist(filestr)
        self.ana_xml(self.nlist)
        return self.root       
         
    def filetostr(self,xmlpath):
        fin = open(xmlpath, 'r', encoding='utf-8')
        return fin.read()
         
    def strtolist(self,filestr):
        pattse = r"<[^>]*>"
        pattcontent = r"(?<=>).*\S.*?(?=<)"
        patt = pattse + r'|' + pattcontent
        nlist = re.findall(patt,filestr)
        return nlist
 
    def ana_xml(self, nlist):
        comment = re.compile(r"<!--[^-]*-->")
        ver = re.compile(r"<?.*\?>")
        startend = re.compile(r"<[^/]*/>")
        start = re.compile(r"<[^>]*>")
        end = re.compile(r"</[^>]*>")
        
        # 获取tag的属性值
        def get_tag_attr(li):
            tag = ''
            attr = {}
            tmp = re.match(r"<\s*([^\s>]+)[\s>]",li)
            if tmp is not None:
                tag = tmp.group(1)
            for key, value in re.findall(r"[ <]([^= ]*)\s*=\s*[\'\"]([^\'\"]*)[\"\']",li):
                attr[key] = value
            return tag, attr
         
        for li in nlist:
            if re.match(comment, li) is not None:
                continue
             
            if re.match(startend, li) is not None:
                tag = ''
                attr = {}
                tag, attr = get_tag_attr(li)
                tnode = XmlNode(tag, attr, self.node)
                if not self.node:
                    self.root = tnode
                else:
                    self.node.add_child(tnode)
                continue
             
            if re.match(ver, li) is not None:
                self.version = li
                continue
             
            if re.match(end, li) is not None:
                if self.node is not None:
                    self.node = self.node.father
                     
            elif re.match(start, li) is not None:
                tag = ''
                attr = {}
                tag, attr = get_tag_attr(li)
                tnode = XmlNode(tag, attr, self.node)
                if not self.node:
                    self.root = tnode
                else:
                    self.node.add_child(tnode)
                self.node = tnode
                 
            else:
                self.node.text = li
     
    def show_tree(self):
        print("The tree is :")
        self.root.show_node()


class XmlNode:
    def __init__(self, tag, attr, father, indent=2):
        self.tag = tag
        self.attr = attr
        self.father = father
        self.text = ''
        self.children = []
        self.indent = ' ' * indent
 
    def add_child(self, node):
        self.children.append(node)
     
    def iter(self, tag):
        result = []
        tmplist = copy.copy(self.children)
        for node in tmplist:
            if node.tag == tag:
                result.append(node)
            tmplist += node.children
        return result
     
    def get(self, key, value=None):
        try:
            value = self.attr[key]
        except:
            pass
        return value
     
    def show_node(self, prefix='', no=0):
        res = '%s<%s> %s %s' % (prefix, self.tag,
              (str(self.attr) if self.attr else ''),
              ((self.text+' ') if self.text else '')) 
        print(res)
        num = len(self.children)
        i = 1    
        for child in self.children:
            if(num == 1):
                child.show_node(prefix + self.indent)
            else:
                child.show_node(prefix + self.indent, i)
            i += 1

2、json与xml互转代码

import json
import os
import traceback as tb
import xmltodict
import xml_parser as xp


def is_valid_json(text):
    """
    判断text是否合法json串
    """
    try:
        j_res = json.loads(text, object_pairs_hook=obj_pairs_hook)
        return True, j_res
    except:
        return False, {'error': tb.format_exc()}


def reg_search(rule, s):
    """
    正则表达式匹配,返回匹配的groups
    """
    import re
    re_obj = re.compile(rule)
    result = re_obj.search(s)
    if result:
        return result.groups()
    else:
        return ()


def json_format(text, indent=2):
    """
    将json格式的text格式化为阅读性好的层级式json
    """
    flag, j_res = is_valid_json(text)
    if flag:
        return json.dumps(j_res, sort_keys=True, indent=indent)
    else:
        error = j_res['error'].split('\n')[-2]
        group = reg_search('.*char (\d+).*', error)
        if not group:
            return error

        col = group[0]
        idx = int(col)

        delta = 20
        start, end = idx - delta, idx + delta
        if idx - delta <= 0: start = 0
        if idx + delta > len(text): end = len(text)
        print('{}'.format(text[start:end]))
        print(' ' * (idx-start) + '^')
        print(' ' * (idx-start-2) + 'error')
        return error


def trans_json_get(text, indent=2):
    """
    json串和url的get参数互转
    """
    import urllib.parse
    res = ''
    try:
        # json to get
        j_data = json.loads(text, object_pairs_hook=obj_pairs_hook)
        for k, v in j_data.items():
            # 处理参数和值中的特殊符号
            k = urllib.parse.quote(str(k))
            v = urllib.parse.quote(str(v))
            res += '{}={}&'.format(k, v)
        return res[:-1]
    except:
        #tb.print_exc()
        # get to json
        import re
        rule = r'.*\?(.*=.*&)+(.*=.*&?)'
        reg = re.compile(rule)
        if not re.match(reg, text):
            text = 'api?' + urllib.parse.unquote(text)
        res = dict(urllib.parse.parse_qsl(urllib.parse.urlsplit(text).query))
        res = json.dumps(res, indent=indent)
        return urllib.parse.unquote(res)


def obj_pairs_hook(lst):
    """
    json串loads时调用的hook函数,将json中重复的key值加入列表中
    e.g.: {"a":1,"a":2}  -> {"a":[1,2]}
    """
    result = {}
    count = {}
    for key, val in lst:
        if key in count: count[key] += 1
        else: count[key] = 1
        if key in result:
            if count[key] > 2: result[key].append(val)
            else: result[key] = [result[key], val]
        else:
            result[key] = val
    return result


def handle_s(s):
    """
    处理特殊符号&<>
    """
    return s.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')


idt = '    '
def parse_list(pk, lst, indent):
    res = idt*indent + '<%s class="array">\n' % pk
    for e in lst:
        type_e = type(e)
        if type_e == str:
            res += idt*(indent+1) + '<e type="string">%s</e>\n' % handle_s(e)
        elif type_e in [int, float]:
            res += idt*(indent+1) + '<e type="number">%s</e>\n' % e
        elif type_e == list:
            res += parse_list('e', e, indent+1)
        elif type_e == dict:
            res += idt*(indent+1) + '<e class="object">\n'
            res += parse_dict(e, indent+1)
            res += '%s</e>\n' % (idt*(indent+1))
    return '%s%s</%s>\n' % (res, idt*indent, pk)


def parse_dict(d, indent):
    res = ''
    for k, v in d.items():
        type_v = type(v)
        if isinstance(k, str): k = handle_s(k)
        if type_v == str:
            res += idt*(indent+1) + '<{0} type="string">{1}</{0}>\n'.format(k, handle_s(v))
        elif type_v in [int, float]:
            res += idt*(indent+1) + '<{0} type="number">{1}</{0}>\n'.format(k, v)
        elif type_v == list:
            res += parse_list(k, v, indent+1)
        elif type_v == dict:
            res += idt*(indent+1) + '<%s class="object">\n' % k
            res += parse_dict(v, indent+1)
            res += '%s</%s>\n' % (idt*(indent+1), k)
    return res


def json_to_xml(j_text):
    res = '<?xml version="1.0" encoding="utf-8"?>\n<xml_root>\n{0}</xml_root>'
    symbols = {'<': '&lt;', '>': '&gt;', '&': '&amp;'}
    tmp = ''
    try:
        # json to get
        j_data = json.loads(j_text, object_pairs_hook=obj_pairs_hook)
        tmp = parse_dict(j_data, 0)
    except:
        tb.print_exc()
    return res.format(tmp)


def trans_xmlnode(node):
    res = ''
    node_class = node.attr.get('class', '')
    node_type = node.attr.get('type', '')
    if node_class == 'array':
        res += '['
        for nc in node.children:
            res += trans_xmlnode(nc)
        res = res[:-1] + ']'
    elif node_class == 'object':
        res += '{'
        for nc in node.children:
            res += '"%s": %s' % (nc.tag, trans_xmlnode(nc))
        res += '}'
    elif node_type == 'number':
        res += '%s' % node.text
    elif node_type == 'string':
        res += '"%s"' % node.text
    res += ','
    return res


def xml_to_json(xml):
    d_res = {}
    if os.path.exists(xml) and xml.endswith('.xml'):
        root = xp.TinyXmlPraser().from_file(xml)
    else:
        root = xp.TinyXmlPraser().from_str(xml)
    for c in root.children:
        if c.text:
            d_res[c.tag] = c.text
        else:
            d_res[c.tag] = trans_xmlnode(c)[:-1]
    for k, v in d_res.items():
        d_res[k] = v.replace(',]', ']').replace(',}', '}')
    return json.dumps(d_res)


def json_to_xml2(j_text):
    res = ''
    try:
        j_data = json.loads(j_text, object_pairs_hook=obj_pairs_hook)
        # json字典长度不为1时,表示json没有根节点
        # 需要手动增加一个根节点xml_root
        if len(j_data) != 1:
            j_data = {'xml_root': j_data}
        res = xmltodict.unparse(j_data, encoding='utf-8')
    except:
        tb.print_exc()
    return res

def xml_to_json2(xml, indent=2):
    if os.path.exists(xml) and xml.endswith('.xml'):
        with open(xml, 'r') as f:
            xml = f.read()
    j_data = xmltodict.parse(xml)
    j_res = json.dumps(j_data, indent=indent)
    return j_res


if __name__ == '__main__':
    text = '{"a": 123, "a":1.2, "a":"<a></a>", "ee": {"c": {"d": "123"}, "cc":[1,3]}, "f": "&ff=f", "g":999, "h":[1,[2,3],{"s":[4,5], "b":333}]}'
    print(text)
    res = json_format(text)
    print('json format result:\n', res)
    print()

    res = trans_json_get(text)
    print('trans json to get:\n', res)
    print()

    #text = 'a=%3Ca%3E%3C/a%3E&b=%5B%27abc%27%2C%201%2C%203%2C%205%5D&e=%7B%27c%27%3A%20%7B%27d%27%3A%20%27123%27%7D%2C%20%27cc%27%3A%20%5B1%2C%203%5D%7D&f=%26ff%3Df&g=999&h=%5B1%2C%202%2C%20%7B%27s%27%3A%20%5B4%2C%205%5D%2C%20%27b%27%3A%20333%7D%5D'
    res = trans_json_get(res)
    print('trans get to json:\n', res)
    print()

    res = json_to_xml(text)
    print('json to xml:\n', res)
    print()

    res = xml_to_json(res)
    print('xml to json:\n', res)
    print()

    res = json_format(res)
    print('json format result:\n', res)
    print()

    res = json_to_xml(text)
    print('json to xml:\n', res)
    print()
    '''
    res = json_to_xml2(text)
    print(res)
    print()

    res = xml_to_json2(res)
    print(res)
    print()
    '''
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于前后端数据传输。JSON字符串格式如下: ``` { "key1": "value1", "key2": "value2", "key3": "value3" } ``` 其中,JSON字符串由一对花括号包围,花括号中包含一个或多个键值对。每个键值对之间用逗号分隔,键和值之间用冒号分隔。键是一个字符串类型,值可以是字符串、数值、布尔值、对象、数组等类型。 例如,以下是一个包含数组和对象的JSON字符串: ``` { "name": "John", "age": 30, "cars": [ { "name": "Ford", "models": ["Fiesta", "Focus", "Mustang"] }, { "name": "BMW", "models": ["320", "X3", "X5"] }, { "name": "Fiat", "models": ["500", "Panda"] } ], "address": { "street": "Main Street", "city": "New York" } } ``` 这个JSON字符串包含了一个名为"name"的键,对应的值是字符串"John";一个名为"age"的键,对应的值是数值30;一个名为"cars"的键,对应的值是一个包含三个对象的数组;一个名为"address"的键,对应的值是一个包含"street"和"city"两个键的对象。 ### 回答2: JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,以字符串的形式表示数据。它由键值对构成,其中键是字符串,值可以是字符串、数字、布尔值、数组、对象或null。 JSON格式字符串的基本结构是由大括号包围的一组键值对,每个键值对之间用逗号分隔。键和值之间使用冒号分开。例如: { "name": "张三", "age": 20, "gender": "男" } 在这个JSON格式字符串中,"name"是键,"张三"是对应的字符串值;"age"是键,20是对应的数字值;"gender"是键,"男"是对应的字符串值。 JSON格式字符串可以嵌套使用,形成复杂的数据结构。例如: { "name": "张三", "age": 20, "gender": "男", "address": { "province": "浙江", "city": "杭州" }, "hobbies": ["篮球", "游泳", "旅行"] } 在这个JSON格式字符串中,"address"是一个对象,包含了"province"和"city"两个键值对;"hobbies"是一个数组,包含了三个字符串元素。 JSON格式字符串具有良好的可读性,易于理解和解析。它被广泛应用于数据交换和存储,特别是在前后端数据传输中常用于代替XML。可以使用不同编程语言的JSON解析器将JSON格式字符串转换为对应的数据结构,以便进一步的处理和操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SoaringXu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值