最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【部分解决】Python输出dict(json)到文件中时确保或指定字段的顺序

Python crifan 4889浏览 0评论

折腾:

【记录】用VSCode开发和调试Python

期间,已经用:

【已解决】python中把dict的json输出到文件且带缩进和不要unicode的\uxxxx

可以输出要的json的内容:

<code>{
  "description": "总结之前使用过有道云笔记和有道云协作的心得供参考", 
  "links": {
    "sidebar": {
      "主页": "https://www.crifan.com"
    }
  }, 
  "author": "Crifan Li &lt;[email protected]&gt;", 
  "title": "有道云笔记和云协作使用总结", 
  "gitbook": "3.2.3", 
  "language": "zh-hans", 
  "plugins": [
    "theme-comscore", 
    "-lunr", 
    "-search", 
    "search-plus", 
    "disqus", 
    "-highlight", 
    "prism", 
    "prism-themes", 
    "github-buttons", 
    "splitter", 
    "-sharing", 
    "sharing-plus", 
    "tbfed-pagefooter", 
    "expandable-chapters-small", 
    "ga", 
    "donate", 
    "sitemap-general", 
    "copy-code-button", 
    "-alerts", 
    "-bootstrap-callout", 
    "callouts", 
    "toolbar-button"
  ], 
  "pluginsConfig": {
    "toolbar-button": {
      "url": "http://book.crifan.com/books/youdao_note_summary/pdf/youdao_note_summary.pdf", 
      "icon": "fa-file-pdf-o", 
      "label": "下载PDF"
    }, 
    "sitemap-general": {
      "prefix": "https://book.crifan.com/gitbook/youdao_note_summary/website/"
    }, 
    "sharing": {
      "qq": true, 
      "douban": false, 
      "all": [
        "douban", 
        "facebook", 
        "google", 
        "instapaper", 
        "line", 
        "linkedin", 
        "messenger", 
        "pocket", 
        "qq", 
        "qzone", 
        "stumbleupon", 
        "twitter", 
        "viber", 
        "vk", 
        "weibo", 
        "whatsapp"
      ], 
      "google": false, 
      "stumbleupon": false, 
      "hatenaBookmark": false, 
      "twitter": true, 
      "vk": false, 
      "linkedin": false, 
      "instapaper": false, 
      "pocket": false, 
      "weibo": true, 
      "viber": false, 
      "facebook": true, 
      "qzone": false, 
      "messenger": false, 
      "line": false, 
      "whatsapp": false
    }, 
    "tbfed-pagefooter": {
      "modify_format": "YYYY-MM-DD HH:mm:ss", 
      "modify_label": "该文件修订时间:", 
      "copyright": "crifan.com,使用&lt;a href='https://creativecommons.org/licenses/by-sa/4.0/deed.zh'&gt;知识署名-相同方式共享4.0协议&lt;/a&gt;发布"
    }, 
    "github-buttons": {
      "buttons": [
        {
          "repo": "youdao_note_summary", 
          "count": true, 
          "type": "star", 
          "user": "crifan", 
          "size": "small"
        }, 
        {
          "count": false, 
          "width": "120", 
          "type": "follow", 
          "user": "crifan", 
          "size": "small"
        }
      ]
    }, 
    "disqus": {
      "shortName": "crifan"
    }, 
    "prism": {
      "css": [
        "prism-themes/themes/prism-atom-dark.css"
      ]
    }, 
    "ga": {
      "token": "UA-28297199-1"
    }, 
    "theme-default": {
      "showLevel": true
    }, 
    "donate": {
      "alipay": "https://www.crifan.com/files/res/crifan_com/crifan_alipay_pay.jpg", 
      "title": "", 
      "alipayText": "支付宝打赏给Crifan", 
      "button": "打赏", 
      "wechatText": "微信打赏给Crifan", 
      "wechat": "https://www.crifan.com/files/res/crifan_com/crifan_wechat_pay.jpg"
    }, 
    "callouts": {
      "showTypeInHeader": false
    }
  }, 
  "root": "./src"
}
</code>

了,但是和原先希望的字段的顺序,有点不一样:

<code>{
  "title": "有道云笔记和云协作使用总结",
  "description": "总结之前使用过有道云笔记和有道云协作的心得供参考",
  "author": "Crifan Li &lt;[email protected]&gt;",
  "language": "zh-hans",
  "gitbook": "3.2.3",
  "root": "./src",
  "links": {
    "sidebar": {
      "主页": "https://www.crifan.com"
    }
  },
  "plugins": [
    "theme-comscore",
    "-lunr",
    "-search",
    "search-plus",
    "disqus",
    "-highlight",
    "prism",
    "prism-themes",
    "github-buttons",
    "splitter",
    "-sharing",
    "sharing-plus",
    "tbfed-pagefooter",
    "expandable-chapters-small",
    "ga",
    "donate",
    "sitemap-general",
    "copy-code-button",
    "-alerts",
    "-bootstrap-callout",
    "callouts",
    "toolbar-button"
  ],
  "pluginsConfig": {
    "callouts": {
      "showTypeInHeader": false
        },
    "theme-default": {
        "showLevel": true
    },
    "disqus": {
      "shortName": "crifan"
    },
    "prism": {
      "css": [
        "prism-themes/themes/prism-atom-dark.css"
      ]
    },
    "github-buttons": {
      "buttons": [
        {
          "user": "crifan",
          "repo": "youdao_note_summary",
          "type": "star",
          "count": true,
          "size": "small"
        }, {
          "user": "crifan",
          "type": "follow",
          "width": "120",
          "count": false,
          "size": "small"
        }
      ]
    },
    "sharing": {
      "douban": false,
      "facebook": true,
      "google": false,
      "hatenaBookmark": false,
      "instapaper": false,
      "line": false,
      "linkedin": false,
      "messenger": false,
      "pocket": false,
      "qq": true,
      "qzone": false,
      "stumbleupon": false,
      "twitter": true,
      "viber": false,
      "vk": false,
      "weibo": true,
      "whatsapp": false,
      "all": [
        "douban",
        "facebook",
        "google",
        "instapaper",
        "line",
        "linkedin",
        "messenger",
        "pocket",
        "qq",
        "qzone",
        "stumbleupon",
        "twitter",
        "viber",
        "vk",
        "weibo",
        "whatsapp"
      ]
    },
    "tbfed-pagefooter": {
      "copyright": "crifan.com,使用&lt;a href='https://creativecommons.org/licenses/by-sa/4.0/deed.zh'&gt;知识署名-相同方式共享4.0协议&lt;/a&gt;发布",
      "modify_label": "该文件修订时间:",
      "modify_format": "YYYY-MM-DD HH:mm:ss"
    },
    "ga": {
      "token": "UA-28297199-1"
    },
    "donate": {
      "wechat": "https://www.crifan.com/files/res/crifan_com/crifan_wechat_pay.jpg",
      "alipay": "https://www.crifan.com/files/res/crifan_com/crifan_alipay_pay.jpg",
      "title": "",
      "button": "打赏",
      "alipayText": "支付宝打赏给Crifan",
      "wechatText": "微信打赏给Crifan"
    },
    "sitemap-general": {
      "prefix": "https://book.crifan.com/gitbook/youdao_note_summary/website/"
    },
    "toolbar-button": {
      "icon": "fa-file-pdf-o",
      "label": "下载PDF",
      "url": "http://book.crifan.com/books/youdao_note_summary/pdf/youdao_note_summary.pdf"
    }
  }
}
</code>

希望此处,可以把:

  “root”: “./src”

等字段,能输出在文件的最开始

python json dump key order

python – Items in JSON object are out of order using “json.dumps”? – Stack Overflow

去试试

OrderedDict

或sort_keys=True

Issue 6105: json.dumps doesn’t respect OrderedDict’s iteration order – Python tracker

18.2. json — JSON encoder and decoder — Python 2.7.15 documentation

“If sort_keys is true (default: False), then the output of dictionaries will be sorted by key.”

<code>json.dump(jsonDict, outputFp, indent=indent, ensure_ascii=False, sort_keys=True)
</code>

结果

先root再title,是根据字母排序了。但是不是我要的效果。

<code>from collections import OrderedDict

json.dump(OrderedDict(jsonDict), outputFp, indent=indent, ensure_ascii=False)
</code>

结果和之前顺序一样,没变化

感觉是:

此处需要:

json文件,去load加载进来时,就要保持order 顺序才行

然后dump输出时,才能用OrderedDict去保持原先顺序的

而load时,此处不知道如何才能保持

python – Can I get JSON to load into an OrderedDict? – Stack Overflow

是我要找的

【总结】

但是弄了半天,其实是已经通过:

<code>
import os
import json
from pprint import pprint
import sys
import copy
import codecs
from collections import OrderedDict


templateJson = {}
currentJson = {}

currPath = os.getcwd()
print("currPath=%s" % currPath)

bookJsonTemplateFullPath = os.path.join(currPath, BookJsonTemplateFilename)
print("bookJsonTemplateFullPath=%s" % bookJsonTemplateFullPath)
# /Users/crifan/GitBook/Library/Import/book_common.json
with open(bookJsonTemplateFullPath) as templateJsonFp:
    # templateJson = json.load(templateJsonFp, encoding="utf-8")
    templateJson = json.load(templateJsonFp, encoding="utf-8", object_pairs_hook=OrderedDict)
    # templateJson = OrderedDict(templateJson)
    # print("type(templateJson)=%s" % (type(templateJson))) #type(templateJson)=&lt;class 'collections.OrderedDict'&gt;

bookJsonCurrentFullPath = os.path.join(currPath, CurrentGitbookName, BookJsonCurrentFilename)
print("bookJsonCurrentFullPath=%s" % bookJsonCurrentFullPath)
with open(bookJsonCurrentFullPath) as currentJsonFp:
    # currentJson = json.load(currentJsonFp, encoding="utf-8")
    currentJson = json.load(currentJsonFp, encoding="utf-8", object_pairs_hook=OrderedDict)
    # currentJson = OrderedDict(currentJson)

bookJsonFullPath = os.path.join(currPath, CurrentGitbookName, BookJsonOutputFilename)
print("bookJsonFullPath=%s" % bookJsonFullPath)
saveJsonToFile(templateJson, bookJsonFullPath)
</code>

是可以在加载之前json文件,并保留字段顺序的

且也可以输出对应的OrderedDict到文件中,也保留了之前的顺序

但是由于此处中间使用了:

<code>
def recursiveMergeDict(aDict, bDict):
    """
    Recursively merge dict a to b, return merged dict b
    Note: Sub dict and sub list's won't be overwritten but also updated/merged

    example:
(1) input and output example:
input:
{
  "keyStr": "strValueA",
  "keyInt": 1,
  "keyBool": true,
  "keyList": [
    {
      "index0Item1": "index0Item1",
      "index0Item2": "index0Item2"
    },
    {
      "index1Item1": "index1Item1"
    },
    {
      "index2Item1": "index2Item1"
    }
  ]
}

and

{
  "keyStr": "strValueB",
  "keyInt": 2,
  "keyList": [
    {
      "index0Item1": "index0Item1_b"
    },
    {
      "index1Item1": "index1Item1_b"
    }
  ]
}

output:

{
  "keyStr": "strValueB", 
  "keyBool": true, 
  "keyInt": 2,
  "keyList": [
    {
      "index0Item1": "index0Item1_b", 
      "index0Item2": "index0Item2"
    }, 
    {
      "index1Item1": "index1Item1_b"
    }, 
    {
      "index2Item1": "index2Item1"
    }
  ]
}

(2) code usage example:
import copy
cDict = recursiveMergeDict(aDict, copy.deepcopy(bDict))

Note:
bDict should use deepcopy, otherwise will be altered after call this function !!!

    """
    aDictItems = None
    if (sys.version_info[0] == 2): # is python 2
      aDictItems = aDict.iteritems()
    else: # is python 3
      aDictItems = aDict.items()

    for aKey, aValue in aDictItems:
      # print("------ [%s]=%s" % (aKey, aValue))
      if aKey not in bDict:
        bDict[aKey] = aValue
      else:
        bValue = bDict[aKey]
        # print("aValue=%s" % aValue)
        # print("bValue=%s" % bValue)
        if isinstance(aValue, dict):
          recursiveMergeDict(aValue, bValue)
        elif isinstance(aValue, list):
          aValueListLen = len(aValue)
          bValueListLen = len(bValue)
          bValueListMaxIdx = bValueListLen - 1
          for aListIdx in range(aValueListLen):
            # print("---[%d]" % aListIdx)
            aListItem = aValue[aListIdx]
            # print("aListItem=%s" % aListItem)
            if aListIdx &lt;= bValueListMaxIdx:
              bListItem = bValue[aListIdx]
              # print("bListItem=%s" % bListItem)
              recursiveMergeDict(aListItem, bListItem)
            else:
              # print("bDict=%s" % bDict)
              # print("aKey=%s" % aKey)
              # print("aListItem=%s" % aListItem)
              bDict[aKey].append(aListItem)

    return bDict

pprint("/"*80)
bookJson = recursiveMergeDict(templateJson, copy.deepcopy(currentJson))
</code>

导致两个json:

templateJson和currentJson

被合并之后,结果输出的字段的顺序,虽然也是OrderedDict,但却不是我们要的效果了。

只能输出这样的结果:

<code>{
  "title": "有道云笔记和云协作使用总结", 
  "description": "总结之前使用过有道云笔记和有道云协作的心得供参考", 
  "pluginsConfig": {
    "github-buttons": {
      "buttons": [
        {
          "repo": "youdao_note_summary", 
          "user": "crifan", 
          "type": "star", 
          "count": true, 
          "size": "small"
        }, 
        {
          "user": "crifan", 
          "type": "follow", 
          "width": "120", 
          "count": false, 
          "size": "small"
        }
      ]
    }, 
    "sitemap-general": {
      "prefix": "https://book.crifan.com/gitbook/youdao_note_summary/website/"
    }, 
    "toolbar-button": {
      "url": "http://book.crifan.com/books/youdao_note_summary/pdf/youdao_note_summary.pdf", 
      "icon": "fa-file-pdf-o", 
      "label": "下载PDF"
    }, 
    "callouts": {
      "showTypeInHeader": false
    }, 
    "theme-default": {
      "showLevel": true
    }, 
    "disqus": {
      "shortName": "crifan"
    }, 
    "prism": {
      "css": [
        "prism-themes/themes/prism-atom-dark.css"
      ]
    }, 
    "sharing": {
      "douban": false, 
      "facebook": true, 
      "google": false, 
      "hatenaBookmark": false, 
      "instapaper": false, 
      "line": false, 
      "linkedin": false, 
      "messenger": false, 
      "pocket": false, 
      "qq": true, 
      "qzone": false, 
      "stumbleupon": false, 
      "twitter": true, 
      "viber": false, 
      "vk": false, 
      "weibo": true, 
      "whatsapp": false, 
      "all": [
        "douban", 
        "facebook", 
        "google", 
        "instapaper", 
        "line", 
        "linkedin", 
        "messenger", 
        "pocket", 
        "qq", 
        "qzone", 
        "stumbleupon", 
        "twitter", 
        "viber", 
        "vk", 
        "weibo", 
        "whatsapp"
      ]
    }, 
    "tbfed-pagefooter": {
      "copyright": "crifan.com,使用&lt;a href='https://creativecommons.org/licenses/by-sa/4.0/deed.zh'&gt;知识署名-相同方式共享4.0协议&lt;/a&gt;发布", 
      "modify_label": "该文件修订时间:", 
      "modify_format": "YYYY-MM-DD HH:mm:ss"
    }, 
    "ga": {
      "token": "UA-28297199-1"
    }, 
    "donate": {
      "wechat": "https://www.crifan.com/files/res/crifan_com/crifan_wechat_pay.jpg", 
      "alipay": "https://www.crifan.com/files/res/crifan_com/crifan_alipay_pay.jpg", 
      "title": "", 
      "button": "打赏", 
      "alipayText": "支付宝打赏给Crifan", 
      "wechatText": "微信打赏给Crifan"
    }
  }, 
  "author": "Crifan Li &lt;[email protected]&gt;", 
  "language": "zh-hans", 
  "gitbook": "3.2.3", 
  "root": "./src", 
  "links": {
    "sidebar": {
      "主页": "https://www.crifan.com"
    }
  }, 
  "plugins": [
    "theme-comscore", 
    "-lunr", 
    "-search", 
    "search-plus", 
    "disqus", 
    "-highlight", 
    "prism", 
    "prism-themes", 
    "github-buttons", 
    "splitter", 
    "-sharing", 
    "sharing-plus", 
    "tbfed-pagefooter", 
    "expandable-chapters-small", 
    "ga", 
    "donate", 
    "sitemap-general", 
    "copy-code-button", 
    "-alerts", 
    "-bootstrap-callout", 
    "callouts", 
    "toolbar-button"
  ]
}
</code>

虽然:

“root”: “./src”,

没有像之前无序输出时被放到最后,但是

<code>  "author": "Crifan Li &lt;[email protected]&gt;", 
  "language": "zh-hans", 
  "gitbook": "3.2.3", 
  "root": "./src", 
  "links": {
    "sidebar": {
      "主页": "https://www.crifan.com"
    }
  },
</code>

这部分,被放到中间了。还不是自己希望的,放在开头的位置的效果。

转载请注明:在路上 » 【部分解决】Python输出dict(json)到文件中时确保或指定字段的顺序

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
82 queries in 0.176 seconds, using 22.12MB memory