Get rid of Mongo $ signs in JSON

蹲街弑〆低调 提交于 2019-12-02 03:05:47

问题


I am building python backend for SPA (Angular) using MongoDB.

Here is what I use: Python 3.4, MongoDB 3, Flask, flask-mongoengine and flask-restful

Now I receive the following JSON from my backend:

[
    {
        "_id": {
            "$oid": "55c737029380f82fbf52eec3"
        },
        "created_at": {
            "$date": 1439129906376
        },
        "desc": "Description.....",
        "title": "This is title"
    },
    etc...
]

And I want to receive something like that:

[
    {
        "_id": "55c737029380f82fbf52eec3",
        "created_at": 1439129906376,
        "desc": "Description.....",
        "title": "This is title"
    },
    etc...
]

My code for now:

from flask import json
from vinnie import app
from flask_restful import Resource, Api
from vinnie.models.movie import Movie

api = Api(app)

class Movies(Resource):
    def get(self):
        movies = json.loads(Movie.objects().all().to_json())
        return movies

api.add_resource(Movies, '/movies')

Model:

import datetime
from vinnie import db

class Movie(db.Document):
    created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
    title = db.StringField(max_length=255, required=True)
    desc = db.StringField(required=True)

    def __unicode__(self):
        return self.title

What is the best way to format convenient JSON for front-end?


回答1:


If you are confident you want to get rid of all the similar cases, then you can certainly write code that matches that pattern. For example:

info = [
    {
        "_id": {
            "$oid": "55c737029380f82fbf52eec3"
        },
        "created_at": {
            "$date": 1439129906376
        },
        "desc": "Description.....",
        "title": "This is title"
    },
    #etc...
]

def fix_array(info):
    ''' Change out dict items in the following case:
           - dict value is another dict
           - the sub-dictionary only has one entry
           - the key in the subdictionary starts with '$'
        In this specific case, one level of indirection
        is removed, and the dict value is replaced with
        the sub-dict value.
    '''
    for item in info:
        for key, value in item.items():
            if not isinstance(value, dict) or len(value) != 1:
                continue
            (subkey, subvalue), = value.items()
            if not subkey.startswith('$'):
                continue
            item[key] = subvalue

fix_array(info)
print(info)

This will return this:

[{'title': 'This is title', 'created_at': 1439129906376, 'desc': 'Description.....', '_id': '55c737029380f82fbf52eec3'}]

Obviously, reformatting that with JSON is trivial.




回答2:


I found a neat solution to my problem in flask-restful extension which I use.

It provides fields module.

Flask-RESTful provides an easy way to control what data you actually render in your response. With the fields module, you can use whatever objects (ORM models/custom classes/etc.) you want in your resource. fields also lets you format and filter the response so you don’t have to worry about exposing internal data structures.

It’s also very clear when looking at your code what data will be rendered and how it will be formatted.

Example:

from flask_restful import Resource, fields, marshal_with

resource_fields = {
    'name': fields.String,
    'address': fields.String,
    'date_updated': fields.DateTime(dt_format='rfc822'),
}

class Todo(Resource):
    @marshal_with(resource_fields, envelope='resource')
    def get(self, **kwargs):
        return db_get_todo()  # Some function that queries the db

Flask-RESTful Output Fields Documentation



来源:https://stackoverflow.com/questions/31904012/get-rid-of-mongo-signs-in-json

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!