You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python jsons库序列化含属性类时字段重复,能否避免?

Python的jsons库序列化带@property的类时出现重复字段,如何避免?

问题背景

原本疑惑为什么jsons库序列化会出现带前置下划线的字段,现在已明确成因,但想解决数据重复序列化的问题。以下示例可复现问题:

示例1:字典序列化符合预期

import jsons

with open('tmp.txt', 'w') as ofile:
    d = {'key': 'value'}
    ofile.write(jsons.dumps(d))

# 输出:
# {"key": "value"}

示例2:普通类(对象)序列化符合预期

import jsons

class Test:
    def __init__(self, value:str) -> None:
        self.value = value

with open('tmp.txt', 'w') as ofile:
    test = Test('value')
    ofile.write(jsons.dumps(test))

# 输出:
# {"value": "value"}

示例3:引入properties后出现重复输出

import jsons

class TestProperty:
    def __init__(self, value:str) -> None:
        self.value = value

    @property
    def value(self) -> str:
        return self._value

    @value.setter
    def value(self, the_value) -> None:
        self._value = the_value

with open('tmp.txt', 'w') as ofile:
    test = TestProperty('value')
    ofile.write(jsons.dumps(test))

# 输出:
# {"_value": "value", "value": "value"}

示例4:改用getter/setter函数后问题消失

import jsons

class TestFunction:
    def __init__(self, value:str) -> None:
        self.value = value

    def get_value(self) -> str:
        return self.value

    def set_value(self, the_value) -> None:
        self.value = the_value

with open('tmp.txt', 'w') as ofile:
    test = TestFunction('value')
    ofile.write(jsons.dumps(test))

# 输出:
# {"value": "value"}

重复原因

jsons库默认的序列化逻辑是:

  1. 遍历对象的所有实例属性(包括_value这种以下划线开头的私有存储字段),将其加入序列化结果;
  2. 同时,@property装饰的方法会被识别为“类属性”,和普通实例属性一样被纳入序列化范围。

这就导致_value(实际存储数据的实例属性)和value(property提供的访问属性)都被序列化,出现重复。而示例4中的getter/setter是普通方法,jsons默认不会序列化方法,所以只保留了value实例属性,没有重复。

解决办法

方法1:序列化时排除指定字段

直接在dumps方法中指定要排除的字段,适合临时处理单个对象:

# 排除单个字段
jsons.dumps(test, exclude={'_value'})

# 通用规则:排除所有以_开头的属性
jsons.dumps(test, exclude=lambda attr_name: attr_name.startswith('_'))

方法2:在类定义时指定序列化规则

用@jsons.serializable装饰器标记类,明确指定要包含的字段,适合长期固定的类序列化规则:

import jsons

@jsons.serializable(include=['value'])
class TestProperty:
    def __init__(self, value:str) -> None:
        self.value = value

    @property
    def value(self) -> str:
        return self._value

    @value.setter
    def value(self, the_value) -> None:
        self._value = the_value

# 序列化后仅输出{"value": "value"}

方法3:自定义序列化函数

针对特定类编写自定义序列化逻辑,适合复杂的定制需求:

import jsons

class TestProperty:
    def __init__(self, value:str) -> None:
        self.value = value

    @property
    def value(self) -> str:
        return self._value

    @value.setter
    def value(self, the_value) -> None:
        self._value = the_value

# 定义序列化函数
def serialize_test_property(obj):
    return {'value': obj.value}

# 绑定到TestProperty类
jsons.set_serializer(serialize_test_property, TestProperty)

# 序列化后仅输出{"value": "value"}
test = TestProperty('value')
jsons.dumps(test)

内容的提问来源于stack exchange,提问作者user2138149

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 07:05:00