2016-11-16 15 views
0

エンドポイントに渡されている複雑なJSONデータ構造を解析するために、カスタムシリアライザをDRFに書き込む方法を理解するのに苦労しています。 JSONは次のようになります。ここではDjango Rest Framework:カスタムJSONシリアライザ

{ 
    "name": "new", 
    "site": "US", 
    "data": { 
     "settings": [], 
     "meta": { 
      "meta1":{} 
     } 
    } 
} 

は、私のバックエンドのコードです:

# views.py 
class SaveData(views.APIView): 
    def post(self, request, *args, **kwargs): 
     name = request.POST.get('name') 
     site = request.POST.get('site') 
     data = request.POST.get('data') 

しかしdataは常にNoneを返します。 requestオブジェクトへの精密検査では、入ってくるJSONは次のようになります。

# POST attribute of request object 
'name' = 'new' 
'site' = 'US' 
'data[settings][0] = '' 
'data[meta][meta1][] = '' 

は基本的にそれが適切にPythonのdictlistオブジェクトにシリアライズ取得されていませんdataキーに関連付けられているネストされたJSONオブジェクトのように見えます。私はカスタムDRFシリアライザの例を探していましたが、私が見つけたもののほとんどはDjangoモデルをシリアライズするためのものでしたが、その必要はありません。着信データはモデルに直接マッピングされません。代わりに、データを保存する前に処理を行う必要があります。

data JSONを適切なPythonオブジェクトに正しく変換するカスタムシリアライザに関するアドバイスをお持ちの方はいらっしゃいますか?私はこれで始まりましたが、例外(When a serializer is passed a 'data' keyword argument you must call '.is_valid()' before attempting to access the serialized '.data' representation. You should either call '.is_valid()' first, or access '.initial_data' instead.)がスローされます。ここに私が作成したカスタムシリアライザのコードがあります:

# serializers.py 
class SaveDataSerializer(serializers.Serializer): 
    name = serializers.CharField() 
    site = serializers.CharField() 
    data = serializers.DictField() 

    def create(self, validated_data): 
     return dict(**validated_data) 

ありがとう。

答えて

0

$.ajaxにJSオブジェクトを渡すと、JSオブジェクトがJSONに変換されて問題を解決することができました。これにより、DRFはPythonオブジェクトを正しく解析できました。何も指定しない場合にはjQueryがContent-Typeとしてx-www-urlencodedがデフォルトになりますけれども

$.ajax({ 
    url: '/api/endpoint', 
    type: 'POST', 
    contentType: 'application/json', 
    data: JSON.stringify(ajaxData), 
    done: function(data) {} 
    ... 
}) 

注:ここでは私が使用しているのjQueryの抜粋です。 JSON.stringify()メソッドを使用して、ajaxDataオブジェクトをJSON文字列に明示的に変換するので、Content-Typeも明示的に設定する必要があります。

私はこれからアイデアを得たSO答え:もちろんConvert Object to JSON string

を、これは本当に私の元の質問に答えていないが、これは簡単ですし、私が望んでいたように動作します別のソリューションです。これにより、私は、任意のカスタムシリアライザを作成する必要はありませんでしたが、私はそうのような私のAPIのビューを変更する必要がありました:

class SaveData(views.APIView): 
    def post(self, request, *args, **kwargs): 
     name = request.data.get('name') 
     site = request.data.get('site') 
     data = request.data.get('data') 

期待オブジェクトの種類が

>>> type(name) 
str 
>>> type(site) 
str 
>>> type(data) 
dict 
を返され、これを行った後
関連する問題