.json 打印数据不遵循 Python 中的字典顺序

The .json printed data doesn't respect the dictionary order in Python

我正在分析一些实时捕获的数据,以解析一些 TLS Client Hello 信息。 捕获和分析数据后,我使用 python.

中的字典将 output.txt 文件中的信息打印为 .json 格式

我的问题是 关于 output.txt 文件中的 .json 输出。数据未按顺序打印,这意味着它不遵守字典中数据的顺序 (output_dictionary.py)。

我用于 .json 输出的词典:

output_dictionary.py

HANDSHAKE = {
    "Client_Hello" : {
        'Length': 'unknown',
        'Version': 'unknown', 
        'Random': 'unknown', 
        'Session ID': 'unknown', 
        'Session ID Length': 'unknown', 
        'Cipher Suites Length': 'unknown',
        'Cipher Suites': 'unknown', 
        'Compression Method': 'unknown'
        }
    }

填充字典以便将其打印为 .json 并调用 json_read("output.txt") 的函数:

def parse_client_hello(handshake):
    if isinstance(handshake.data, dpkt.ssl.TLSClientHello):
        client = dpkt.ssl.TLSClientHello(str(handshake.data))
        **HANDSHAKE["Client_Hello"]['Length'] = len(client)**
        **HANDSHAKE["Client_Hello"]['Version'] = tls_dictionary('tls_version',client.version)**
        
        **HANDSHAKE["Client_Hello"]['Random'] = hexlify(client.random)**
        
        session_id, pointer = parse(client.data, 1)
        **HANDSHAKE["Client_Hello"]['Session ID'] = hexlify(session_id)**
        **HANDSHAKE["Client_Hello"]['Session ID Length'] = len(session_id)**
        
        ciphersuites, pointer1 = parse(client.data[pointer:], 2)
        ciphersuites, pretty_cipher_suites = parse_ciphers_compressions(ciphersuites, 'cipher_suites')
        **HANDSHAKE["Client_Hello"]['Cipher Suites Length'] = len(ciphersuites)**
        **HANDSHAKE["Client_Hello"]['Cipher Suites'] = pretty_cipher_suites**
        
        pointer += pointer1 
        compression_methods, pointer1 = parse(client.data[pointer:], 1)
        compression_methods, pretty_compressions = parse_ciphers_compressions(compression_methods,
            'compression_methods')
        **HANDSHAKE["Client_Hello"]['Compression Method'] = pretty_compressions**

        json_read("output.txt")

将字典转换为.json格式的json.read函数:

def json_read(filename):
    with open(filename, "a") as f:
        json.dump(HANDSHAKE, f, indent = 4)
    

数据如何以 .json 格式打印在 ouput.txt 文件中:

{
    "Client_Hello": {
        "Session ID Length": 32, 
        "Length": 236, 
        "Version": "TLS 1.2", 
        "Handshake Type": "Client Hello : 1", 
        "Compression Method": [
            "null"
        ], 
        "Session ID": "3eadfb1c6243f6aa70a880af598d52873e1fe049f15c3a7e2e6f4a3e4b58fc0e", 
        "Random": "502143b34cab4a59f947a8da76f58e66215bf709e85f71f7cbfa4ead8e99736b", 
        "Cipher Suites Length": 15, 
        "Cipher Suites": [
            "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 
            "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", 
            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", 
            "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 
            "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 
            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 
            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 
            "TLS_RSA_WITH_AES_128_GCM_SHA256", 
            "TLS_RSA_WITH_AES_256_GCM_SHA384", 
            "TLS_RSA_WITH_AES_128_CBC_SHA", 
            "TLS_RSA_WITH_AES_256_CBC_SHA", 
            "TLS_RSA_WITH_3DES_EDE_CBC_SHA"
        ]
    }
}

问题是 .json 打印的数据不遵守字典顺序,这意味着首先它应该打印长度、版本、随机数等。 有办法解决这个问题吗?

基本上你的问题归结为“保持 keys/values 与初始化字典时声明的顺序相同”。为此,您必须使用 OrderedDict。 OrderedDict 维护您的密钥插入的顺序。

对于您的情况,您可以像下面这样初始化 HANDSHAKE 字典:

from collections import OrderedDict
client_hello_params = ['Length', 'Version', 'Random', 'Session ID', 'Session ID Length', 'Cipher Suites Length', 'Cipher Suites', 'Compression Method']
HANDSHAKE = {
"Client_Hello": OrderedDict((param, 'unknown') for param in client_hello_params)

现在您可以通过更改 client_hello_params 列表中的顺序来保留您想要的任何顺序。

打印这将打印您想要的结果,例如。

import json
HANDSHAKE["Client_Hello"]['Length'] = 10
print(json.dumps(HANDSHAKE))
{"Client_Hello": {"Length": 10, "Version": "unknown", "Random": "unknown", "Session ID": "unknown", "Session ID Length": "unknown", "Cipher Suites Length": "unknown", "Cipher Suites": "unknown", "Compression Method": "unknown"}}