Python中对象转Json

如何用python和redis交互呢?
该怎样定义数据存储格式,从而使得数据跨平台使用?当然是Json
并在其他项目中,采用redis缓存进行读取,并由Python进行写入。

这里就简单记录两种语言在读写写Json时候需要注意的点。

Python 的Json.dumps

Json模块的dumps方法,用于将对象转化为json格式的string对象,
简单看看dumps的定义:

def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        default=None, sort_keys=False, **kw):
  • skipkeys: 标识会跳过某些key,这样就算这些key不是基本类型(str, int, float, bool, None),那么执行dumps方法,也不会抛出异常。
  • ensure_ascii:保证转化后的为ascii码类型
  • default:一个func,函数,用于返回一个可序列化版本的对象,或者raise TypeError,默认就是抛出TypeError
  • indent:为一个非负的整数,表示Json块之间的缩进数,一般为4个空格。

注意,在Java中,一些成型的库例如jackson,fastjson,都已经帮我们完成了各种转json的骚操作,但是在python中,有些情况则需要手动调用dumps方法来完成转Json。

多层嵌套对象

通常,在一个单一的对象中,使用json.dumps可以完成对象转json操作,但是当多个对象签到,
例如:

class Father(object):
    """dto"""
    def __init__(self, Son1, Son2, Son3, Son4):
        self.Son1= Son1
        self.Son2= Son2
        self.Son3= Son3
        self.Son4= Son4

这样一来,由于Son*不是python中懂得基本类型,所以我们需要自己重写一个方法,手动调用json.dumps,从而完成转化,否则会报序列化错误:

TypeError: <_io.BytesIO object at 0x7f81c3153728> is not JSON serializable

此时,则需要往Father中,增加一个方法,手动实现对json.dumps的调用即可:

    def to_json(self):
        return json.dumps(self, default=lambda o: o.__dict__,
                          sort_keys=True, indent=4)

这样完成就是一个标准的json格式了。

Java中的转化

在Java方面,使用Spring Data Redis来管理Redis,通常,在一个项目中,会配置一个RedisTemplete:

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new Jackson2JsonRedisSerializer);
        return template;
    }

如上,我们可以设置KeySerializer,也可以设置ValueSerilizer,当然,此时,就可以吧Jackson的Serilizer设置进去,此处不过多介绍Jackson的序列化器。另外提一点,如果不设置KeysSerializer,可能会出现乱码情况。

上面的配置,在一个项目中往往不会出现任何问题,因为项目是统一的,从Java对象到Json,是用这个Serializer,从Json到Java对象,也是这个Serializer,但是,如果不同项目中,需要通过Json来传递某些信息,那么就可能会出问题了。

可以了解,其实在Jackson中,有几种Serializer,他们的序列化之后的字符串,虽然是json格式,但是却会有某些区别,
主要有:Jackson2JsonRedisSerializerGenericJackson2JsonRedisSerializer。具体自行理解。

所以在从redis中读取数据时候,需要根据其他语言(例如python)写入的格式,进行解码,必要时需要重写一个Serializer进行解码操作:

例如下面是一个简单地VlueSerializer:

public class PythonJacksonSerializer<T> implements RedisSerializer<T> {
    private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    private final Charset charset;
    private ObjectMapper objectMapper = new ObjectMapper();
    private Class clazz;

    public PythonJacksonSerializer(Charset charset, Class clazz) {
        Assert.notNull(charset, "Charset must not be null!");
        this.charset = charset;
        this.clazz = clazz;
    }

    public PythonJacksonSerializer(Class clazz) {
        this(Charset.forName("UTF-8"), clazz);
    }
    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        try {
            return this.objectMapper.writeValueAsBytes(t);
        } catch (Exception ex) {
            throw new SerializationException("Could not write JSON: " + ex.getMessage(), ex);
        }
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        String jsonStr = new String(bytes, charset);
        try {
            return (T)JSONUtils.json2pojo(jsonStr, this.clazz);
        } catch (Exception e) {
            LOGGER.error("PythonJacksonSerializer occurs error",e.getMessage());
            e.printStackTrace();
        }
        return null;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值