Home > Blockchain >  How to deserialize a list to '<class 'str'>' for SubTaskRuleRes.content,
How to deserialize a list to '<class 'str'>' for SubTaskRuleRes.content,

Time:12-19

This is my definition dto class:

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace DeserializeDemo
{
    public class SubTaskRuleDto
    {
        public Guid Id { get; set; }

        [JsonConverter(typeof(ByteArrayConverter))]
        public byte[] Content { get; set; }

        public bool DisableImage { get; set; }

        public bool UseMobileAgent { get; set; }

        public bool SupplementEnable { get; set; }
    }

    public class ByteArrayConverter : JsonConverter<byte[]>
    {
        public override byte[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            short[] sByteArray = JsonSerializer.Deserialize<short[]>(ref reader);
            byte[] value = new byte[sByteArray.Length];
            for (int i = 0; i < sByteArray.Length; i  )
            {
                value[i] = (byte)sByteArray[i];
            }

            return value;
        }

        public override void Write(Utf8JsonWriter writer, byte[] value, JsonSerializerOptions options)
        {
            writer.WriteStartArray();

            foreach (var val in value)
            {
                writer.WriteNumberValue(val);
            }

            writer.WriteEndArray();
        }
    }
}

Then I Will show the asp.net core Controller code:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;

namespace DeserializeDemo.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class Clouds : ControllerBase
    {
        private readonly ILogger<Clouds> _logger;

        public Clouds(ILogger<Clouds> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public SubTaskRuleDto Get()
        {
            return new SubTaskRuleDto()
            {
                Id = Guid.NewGuid(),
                Content = new byte[] { 1, 7},
                DisableImage = false,
                UseMobileAgent = true,
                SupplementEnable = false,
            };
        }

        public enum ContentType
        {
            Xoml = 1,
            Python = 7,
            NodeJS = 8
        }
    }
}
The api works well, and test ok in postman: enter image description here

When I call the api in my python client, my code just like this:

# -*- coding:utf-8 -*-
import json
import deserialize
import requests


class SubTaskRuleRes:
    id: str
    content: str
    disableImage: bool
    useMobileAgent: bool
    supplementEnable: bool


def get_subtask_rule():
    url = "http://localhost:5000/clouds"
    res = requests.get(url)

    # print(res.content)
    # binary = res.content
    # output = json.loads(binary)

    my_instance = deserialize.deserialize(SubTaskRuleRes, res.json())
    print(my_instance)

get_subtask_rule()

deserialize- 1.8.3 - https://github.com/dalemyers/deserialize

The problem is I Cannot deserialize a list to '<class 'str'>' or a list for SubTaskRuleRes.content.

CodePudding user response:

deserialize does not perform implicit type conversion. That is the reason for the error you get (note, always post the full traceback you get).

Looking at the docs, you can use decorator to pass a parser function (look at Advanced Usage/Parsers, e.g.

import deserialize

@deserialize.parser("content", str)
class SubTaskRuleRes:
    id: str
    content: str
    disableImage: bool
    useMobileAgent: bool
    supplementEnable: bool
    

def get_subtask_rule():
    spam = {'id':'28631ee-abd', 'content':[1, 7],
            'disableImage': False, 'useMobileAgent':True,
            'supplementEnable': False}
    return deserialize.deserialize(SubTaskRuleRes, spam)

rule = get_subtask_rule()
print(rule.content)
print(type(rule.content))

output

[1, 7]
<class 'str'>

Note, I am not sure why would you want content to be list literal, string

  • Related