27

フロントエンドの対応する Web API サーバーとして機能する python/django アプリケーションに取り組んでいます。サーバーとクライアント間のデータ交換は、XMLHttpRequest (Javascript) を使用した JSON 形式です。Python と Javascript の両方に精通している人は、変数/メソッド/属性に関しては、識別子の命名規則が異なることを知っています。Python はnames_with_underscoresJavaScript が好むのに対し、を使用しcamelCaseNamesます。両方の規則をそれぞれの世界で維持し、データ交換が発生したときに識別子の変換を実行したいと考えています。

サーバー (Python) で変換を実行することにしました。私自身の意見では、この双方向の変換が発生する最も論理的な場所は、JSON のシリアル化/逆シリアル化の間です。このアプローチを実装するにはどうすればよいですか?例は高く評価されています。

私はPython 2.7を使用していることに注意してください。

4

7 に答える 7

25

正規表現を使用してそれを行う1つの方法、

import re

camel_pat = re.compile(r'([A-Z])')
under_pat = re.compile(r'_([a-z])')

def camel_to_underscore(name):
    return camel_pat.sub(lambda x: '_' + x.group(1).lower(), name)

def underscore_to_camel(name):
    return under_pat.sub(lambda x: x.group(1).upper(), name)

と、

>>> camel_to_underscore('camelCaseNames')
'camel_case_names'
>>> underscore_to_camel('names_with_underscores')
'namesWithUnderscores'

: 大文字と小文字の変更を行うには関数 (lambdaここでは式) を使用する必要がありますが、これは非常に簡単に思えます。

編集:

Python と Javascript の間で json オブジェクトをインターセプトして調整したい場合は、json モジュールの機能を書き直す必要があります。しかし、それは価値があるよりもはるかに面倒だと思います。代わりに、このようなものは同等であり、パフォーマンス面であまりヒットしません.

json オブジェクトを表す各キーを変換するにはdict、次のようにします。

def convert_json(d, convert):
    new_d = {}
    for k, v in d.iteritems():
        new_d[convert(k)] = convert_json(v,convert) if isinstance(v,dict) else v
    return new_d

適用する関数を指定するだけで済みます。

>>> json_obj = {'nomNom': {'fooNom': 2, 'camelFoo': 3}, 'camelCase': {'caseFoo': 4, 'barBar': {'fooFoo': 44}}}
>>> convert_json(json_obj, camel_to_underscore)
{'nom_nom': {'foo_nom': 2, 'camel_foo': 3}, 'camel_case': {'case_foo': 4, 'bar_bar': {'foo_foo': 44}}}

このすべてのロジックを new関数loaddump関数でラップできます。

import json

def convert_load(*args, **kwargs):
    json_obj = json.load(*args, **kwargs)
    return convert_json(json_obj, camel_to_underscore)

def convert_dump(*args, **kwargs):
    args = (convert_json(args[0], underscore_to_camel),) + args[1:]
    json.dump(*args, **kwargs)

そして、 then と同じように使用しjson.loadますjson.dump

于 2013-06-17T20:38:53.117 に答える
16

Jared の答えは、json オブジェクト構造内のオブジェクトを含む配列の可能性を考慮していません。

このソリューションでは、配列を再帰的に処理するために 3 つの関数が必要です。

CamelCase から underscores_with_spaces への変換の場合:

def convert(s):
    a = re.compile('((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))')
    return a.sub(r'_\1', s).lower()

json オブジェクトの場合

def convertJSON(j):
    out = {}
    for k in j:
        newK = convert(k)
        if isinstance(j[k],dict):
            out[newK] = convertJSON(j[k])
        elif isinstance(j[k],list):
            out[newK] = convertArray(j[k])
        else:
            out[newK] = j[k]
    return out

json オブジェクト内の配列の場合:

def convertArray(a):
    newArr = []
    for i in a:
        if isinstance(i,list):
            newArr.append(convertArray(i))
        elif isinstance(i, dict):
            newArr.append(convertJSON(i))
        else:
            newArr.append(i)
    return newArr

使用法:

convertJSON({
    "someObject": [
        {
            "anotherObject": "CamelCaseValue"
        },
        {
            "anotherObject": "AnotherCamelCaseValue"
        }
    ]
})

収量:

{
    'some_object': [
        {
            'another_object': 'CamelCaseValue'
        },
        {
            'another_object': 'AnotherCamelCaseValue'
        }
    ]
}
于 2014-02-13T00:05:52.837 に答える