python পাইথন JSON একটি দশমিক বস্তু serialize



floating-point decimal (12)

3.9 IEEE ফ্লোটগুলিতে 3.8999999999999999 উপস্থাপিত করা যাবে না, এটি সর্বদা 3.8999999999999999 হিসাবে 3.8999999999999999 , যেমন print repr(3.9) চেষ্টা করুন, আপনি এখানে এটি সম্পর্কে আরও পড়তে পারেন:

http://en.wikipedia.org/wiki/Floating_point
http://docs.sun.com/source/806-3568/ncg_goldberg.html

সুতরাং আপনি যদি ফ্লোটটি না চান তবে শুধুমাত্র বিকল্পটি আপনাকে স্ট্রিং হিসাবে পাঠাতে হবে এবং দশমিক বস্তুর স্বয়ংক্রিয়ভাবে JSON এ রূপান্তর করার অনুমতি দিতে, এর মতো কিছু করুন:

import decimal
from django.utils import simplejson

def json_encode_decimal(obj):
    if isinstance(obj, decimal.Decimal):
        return str(obj)
    raise TypeError(repr(obj) + " is not JSON serializable")

d = decimal.Decimal('3.5')
print simplejson.dumps([d], default=json_encode_decimal)

আমার একটি বস্তুর অংশ হিসাবে Decimal('3.9') , এবং একটি JSON স্ট্রিং এ এনকোড করতে চান যা {'x': 3.9} মতো হওয়া উচিত। আমি ক্লায়েন্ট পাশে স্পষ্টতা সম্পর্কে যত্ন না, তাই একটি ভাসা জরিমানা।

এই serialize করার একটি ভাল উপায় আছে কি? JSONDecoder দশমিক বস্তু গ্রহণ করে না এবং একটি ফ্ল্যাটে রূপান্তরিত হওয়ার পূর্বে {'x': 3.8999999999999999} যা {'x': 3.8999999999999999} তা ভুল, এবং এটি ব্যান্ডউইথের একটি বড় বর্জ্য হবে।


Answer #1

আমি জিএইচ 2.7 এর জন্য সহজজসন থেকে বিল্টিন জসন থেকে স্যুইচিং করার চেষ্টা করেছি এবং দশমিকের সাথে সমস্যা ছিল। ডিফল্ট ফিরে str (o) উদ্ধৃতি ছিল (কারণ _iterencode কল ডিফল্ট ফলাফল _iterencode কল), এবং float (ও) পিছনে 0 মুছে ফেলা হবে।

ডিফল্ট ফ্ল্যাট থেকে প্রাপ্ত উত্তরাধিকারী (অথবা যে কোনও অতিরিক্ত ফর্ম্যাট ছাড়াই repr কে কল করে) একটি অবজেক্ট ফেরত পাঠায় এবং এটি একটি কাস্টম __repr__ পদ্ধতি থাকে তবে মনে হচ্ছে আমি এটি করতে চাই।

import json
from decimal import Decimal

class fakefloat(float):
    def __init__(self, value):
        self._value = value
    def __repr__(self):
        return str(self._value)

def defaultencode(o):
    if isinstance(o, Decimal):
        # Subclass float with custom repr?
        return fakefloat(o)
    raise TypeError(repr(o) + " is not JSON serializable")

json.dumps([10.20, "10.20", Decimal('10.20')], default=defaultencode)
'[10.2, "10.20", 10.20]'

Answer #2

আপনি যদি requests লাইব্রেরি ( simplejson কীওয়ার্ড আর্গুমেন্ট ব্যবহার করে) এর দশমিক ধারণকারী অভিধানটি পাস করতে চান তবে আপনাকে কেবল simplejson ইনস্টল করতে হবে:

$ pip3 install simplejson    
$ python3
>>> import requests
>>> from decimal import Decimal
>>> # This won't error out:
>>> requests.post('https://www.google.com', json={'foo': Decimal('1.23')})

সমস্যার কারণ হল এটি উপস্থিত থাকলে কেবলমাত্র simplejson ব্যবহার করে, এবং এটি ইনস্টল করা না থাকলে বিল্ট-ইন simplejson ফিরে আসে।


Answer #3

Simplejson 2.1 এবং উচ্চতর দশমিক ধরন জন্য নেটিভ সমর্থন আছে:

>>> json.dumps(Decimal('3.9'), use_decimal=True)
'3.9'

উল্লেখ্য যে use_decimal ডিফল্টরূপে True :

def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
    allow_nan=True, cls=None, indent=None, separators=None,
    encoding='utf-8', default=None, use_decimal=True,
    namedtuple_as_object=True, tuple_as_array=True,
    bigint_as_string=False, sort_keys=False, item_sort_key=None,
    for_json=False, ignore_nan=False, **kw):

তাই:

>>> json.dumps(Decimal('3.9'))
'3.9'

আশা করি, এই বৈশিষ্ট্যটি স্ট্যান্ডার্ড লাইব্রেরিতে অন্তর্ভুক্ত করা হবে।


Answer #4

এই যোগ করে সম্পন্ন করা যেতে পারে

    elif isinstance(o, decimal.Decimal):
        yield str(o)

\Lib\json\encoder.py:JSONEncoder._iterencode , কিন্তু আমি একটি ভাল সমাধান আশা করছি


Answer #5

আমার ফ্লাস্ক অ্যাপে পাইথন 2.7.11, ফ্লাস আলকমি ('ডিবি ডিকিমাল' প্রকারের সাথে), এবং ফ্লাস্ক মার্শমালো ('ইনস্ট্যান্ট' সিরিয়ালাইজার এবং ডেসেরিয়ালাইজারের জন্য) ব্যবহার করে, আমার এই ত্রুটি ছিল, প্রতিবার আমি কোনও পোস্ট বা পোস্ট পেয়েছিলাম । Serializer এবং deserializer, কোনও JSON শনাক্তযোগ্য বিন্যাসে দশমিক ধরন রূপান্তর করতে ব্যর্থ হয়েছে।

আমি একটি "পিপ ইনস্টল simplejson", তারপর শুধু যোগ করে

import simplejson as json

serializer এবং deserializer আবার purr শুরু। আমি আর কিছুই করিনি ... ডিসিমলগুলি '234.00' ফ্ল্যাট ফর্ম্যাট হিসাবে প্রদর্শিত হয়।


Answer #6

JSON স্ট্যান্ডার্ড ডকুমেন্ট থেকে , json.org লিঙ্ক হিসাবে:

JSON সংখ্যার semantics সম্পর্কে অগ্নিকুণ্ড হয়। কোনও প্রোগ্রামিং ভাষাতে বিভিন্ন ধরণের বিভিন্ন বৈশিষ্ট্য এবং সম্পূরক, নির্দিষ্ট বা ভাসমান, বাইনারি বা দশমিক হতে পারে। যে বিভিন্ন প্রোগ্রামিং ভাষা কঠিন মধ্যে বিনিময় করতে পারেন। পরিবর্তে JSON মানুষের সংখ্যা ব্যবহার করে প্রতিনিধিত্ব করে: সংখ্যাগুলির একটি ক্রম। সমস্ত প্রোগ্রামিং ভাষাগুলি জানেন যে কিভাবে ডিজিটাল সিকোয়েন্সগুলি বোঝা যায় এমনকি যদি তারা অভ্যন্তরীণ উপস্থাপনাগুলিতে অসম্মতি প্রকাশ করে। যে বিনিময় অনুমতি যথেষ্ট।

সুতরাং JSON এ সংখ্যাগুলি (স্ট্রিংয়ের পরিবর্তে) হিসাবে দশমিককে প্রতিনিধিত্ব করার জন্য এটি আসলে সঠিক। Bellow সমস্যা একটি সম্ভাব্য সমাধান মিথ্যা।

একটি কাস্টম JSON এনকোডার নির্ধারণ করুন:

import json


class CustomJsonEncoder(json.JSONEncoder):

    def default(self, obj):
        if isinstance(obj, Decimal):
            return float(obj)
        return super(CustomJsonEncoder, self).default(obj)

তারপর আপনার তথ্য serializing যখন এটি ব্যবহার করুন:

json.dumps(data, cls=CustomJsonEncoder)

অন্য উত্তরের মন্তব্যগুলি থেকে যেমন উল্লেখ করা হয়েছে, পাইথনের পুরানো সংস্করণগুলি ফ্লোটে রূপান্তর করার সময় প্রতিনিধিত্বকে আপত্তিজনক করে তুলতে পারে, কিন্তু এটি এখন আর নয়।

পাইথন দশমিক ফিরে পেতে:

Decimal(str(value))

এই সমাধানটি পাইথন 3.0 ডকুমেন্টেশনগুলিতে দশমিকের উপর ইঙ্গিত করা হয়েছে:

একটি ভাসা থেকে একটি দশমিক তৈরি করতে, প্রথমে এটি একটি স্ট্রিং রূপান্তর।


Answer #7

আমি প্রত্যেককে জানাতে চাই যে আমি পাইথন 2.6.5 চালানোর সময় আমার ওয়েব সার্ভারে Michał Marczyk এর উত্তর দেওয়ার চেষ্টা করেছি এবং এটি জরিমানা হয়েছে। যাইহোক, আমি পাইথন 2.7 তে আপগ্রেড করেছি এবং এটি কাজ বন্ধ করে দিয়েছে। আমি দশমিক বস্তু এনকোড করার জন্য কিছু ধরণের উপায় চিন্তা করার চেষ্টা করেছি এবং এইটি আমি এগুলি নিয়ে এসেছি:

class DecimalEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, decimal.Decimal):
            return float(o)
        return super(DecimalEncoder, self).default(o)

এইটি Python 2.7 এর সাথে কোনও সমস্যা আছে এমন কাউকে সহায়তা করতে হবে। আমি এটা পরীক্ষিত এবং এটা জরিমানা কাজ বলে মনে হচ্ছে। যদি কেউ আমার সমাধান কোন বাগ নোটিশ বা একটি ভাল উপায় সঙ্গে আসে, দয়া করে আমাকে জানাতে।


Answer #8

নেটিভ বিকল্পটি অনুপস্থিত, তাই আমি পরবর্তী লোক / গালের জন্য এটি জুড়ে দেব।

Django 1.7.x থেকে শুরু হচ্ছে একটি অন্তর্নির্মিত DjangoJSONEncoder যা আপনি এটি django.core.serializers.json থেকে পেতে পারেন।

import json
from django.core.serializers.json import DjangoJSONEncoder
from django.forms.models import model_to_dict

model_instance = YourModel.object.first()
model_dict = model_to_dict(model_instance)

json.dumps(model_dict, cls=DjangoJSONEncoder)

Presto!


Answer #9

std''OrgnlDave উত্তরের উপর ভিত্তি করে আমি এই std''OrgnlDave সংজ্ঞায়িত করেছি যে এটি ঐচ্ছিক ধরণের সহ বলা যেতে পারে যাতে এনকোডার কেবলমাত্র আপনার প্রোজেক্টের ভিতরে নির্দিষ্ট ধরণের জন্য কাজ করবে। আমি বিশ্বাস করি যে আপনার কোডের ভিতরে কাজটি করা উচিত এবং "ডিফল্ট" এনকোডারটি ব্যবহার করা হবে না কারণ এটি "অন্তর্নিহিত চেয়ে স্পষ্টতর স্পষ্ট" তবে আমি বুঝি এটি ব্যবহার করে আপনার কিছু সময় বাঁচাবে। :-)

import time
import json
import decimal
from uuid import UUID
from datetime import datetime

def JSONEncoder_newdefault(kind=['uuid', 'datetime', 'time', 'decimal']):
    '''
    JSON Encoder newdfeault is a wrapper capable of encoding several kinds
    Use it anywhere on your code to make the full system to work with this defaults:
        JSONEncoder_newdefault()  # for everything
        JSONEncoder_newdefault(['decimal'])  # only for Decimal
    '''
    JSONEncoder_olddefault = json.JSONEncoder.default

    def JSONEncoder_wrapped(self, o):
        '''
        json.JSONEncoder.default = JSONEncoder_newdefault
        '''
        if ('uuid' in kind) and isinstance(o, uuid.UUID):
            return str(o)
        if ('datetime' in kind) and isinstance(o, datetime):
            return str(o)
        if ('time' in kind) and isinstance(o, time.struct_time):
            return datetime.fromtimestamp(time.mktime(o))
        if ('decimal' in kind) and isinstance(o, decimal.Decimal):
            return str(o)
        return JSONEncoder_olddefault(self, o)
    json.JSONEncoder.default = JSONEncoder_wrapped

# Example
if __name__ == '__main__':
    JSONEncoder_newdefault()

Answer #10

এই আমি আছে, আমাদের ক্লাস থেকে আহৃত

class CommonJSONEncoder(json.JSONEncoder):

    """
    Common JSON Encoder
    json.dumps(myString, cls=CommonJSONEncoder)
    """

    def default(self, obj):

        if isinstance(obj, decimal.Decimal):
            return {'type{decimal}': str(obj)}

class CommonJSONDecoder(json.JSONDecoder):

    """
    Common JSON Encoder
    json.loads(myString, cls=CommonJSONEncoder)
    """

    @classmethod
    def object_hook(cls, obj):
        for key in obj:
            if isinstance(key, six.string_types):
                if 'type{decimal}' == key:
                    try:
                        return decimal.Decimal(obj[key])
                    except:
                        pass

    def __init__(self, **kwargs):
        kwargs['object_hook'] = self.object_hook
        super(CommonJSONDecoder, self).__init__(**kwargs)

যা একক পাস করে:

def test_encode_and_decode_decimal(self):
    obj = Decimal('1.11')
    result = json.dumps(obj, cls=CommonJSONEncoder)
    self.assertTrue('type{decimal}' in result)
    new_obj = json.loads(result, cls=CommonJSONDecoder)
    self.assertEqual(new_obj, obj)

    obj = {'test': Decimal('1.11')}
    result = json.dumps(obj, cls=CommonJSONEncoder)
    self.assertTrue('type{decimal}' in result)
    new_obj = json.loads(result, cls=CommonJSONDecoder)
    self.assertEqual(new_obj, obj)

    obj = {'test': {'abc': Decimal('1.11')}}
    result = json.dumps(obj, cls=CommonJSONEncoder)
    self.assertTrue('type{decimal}' in result)
    new_obj = json.loads(result, cls=CommonJSONDecoder)
    self.assertEqual(new_obj, obj)

Answer #11

json.JSONEncoder subclassing সম্পর্কে কিভাবে?

class DecimalEncoder(json.JSONEncoder):
    def _iterencode(self, o, markers=None):
        if isinstance(o, decimal.Decimal):
            # wanted a simple yield str(o) in the next line,
            # but that would mean a yield on the line with super(...),
            # which wouldn't work (see my comment below), so...
            return (str(o) for o in [o])
        return super(DecimalEncoder, self)._iterencode(o, markers)

তারপরে এটি ব্যবহার করুন:

json.dumps({'x': decimal.Decimal('5.5')}, cls=DecimalEncoder)




decimal