当前位置: 首页 > 知识库问答 >
问题:

根据JSON属性转换为特定类型[重复]

巴英韶
2023-03-14

我有一个包含水果列表的字符串。我的 C# 程序不能直接使用 Fruit,它需要将它们转换为 Banana 或 Apple。有关强制转换它们的信息包含在 json 的构造函数属性中。

注意:我使用的是JSON.NET。

这是我想要达到的目标:

    class Fruit{ public string constructor;}
    class Banana : Fruit { public int monkey;}
    class Apple : Fruit { public string shape;}

    string json = @"[
            {
                ""constructor"":""banana"",
                ""monkey"":1
            },
            {
                ""constructor"":""apple"",
                ""shape"":""round""
            }]";
        List<Fruit> fruitList = JsonConvert.DeserializeObject<List<Fruit>>(json);
        List<Banana> bananaList = new List<Banana>();
        List<Apple> appleList = new List<Apple>();
        foreach(var fruit in fruitList){
            if(fruit.constructor == "banana") bananaList.Add((Banana)fruit); //bug
            if(fruit.constructor == "apple") appleList.Add((Apple)fruit); //bug
        }

        //use bananaList and appleList for stuff

但是,我不能进行强制转换。有什么方法可以让bananaList包含json中的所有对象,这些对象的构造函数属性设置为"banana"并且与apple eList相同?

解决方案:

    public static string objToJson(object obj) {
        return JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings {
            TypeNameHandling = TypeNameHandling.Auto
        });
    }
    public static T jsonToObj<T>(string str) {
        return JsonConvert.DeserializeObject<T>(str, new JsonSerializerSettings {
            TypeNameHandling = TypeNameHandling.Auto
        });
    }

共有3个答案

羊舌高爽
2023-03-14

JSON.NET 只能解析它期望解析的内容。它无法假定它要使用的类的哪个多态子级。

如果可以控制源 JSON,则可以告诉序列化程序包含有关正在使用的类型的数据。

如果没有,我相信您需要手动读取数据(或通过JTokens或类似方式),以找到构造函数财产,然后再告诉它解析正确的类型。

陆星文
2023-03-14

您试图进行多态反序列化,但您要求反序列化程序将反序列化为水果列表。您不能向上转换到Apple/Banana,因为实例的类型是Fruit。

如果您可以控制json,则可以保存其中包含类型信息的json,并且反序列化器将自动创建正确的类型。

public class Fruit{  }
public class Banana : Fruit { public int monkey;}
public class Apple : Fruit { public string shape;}

class Program
{
    static void Main(string[] args)
    {
        var list = new List<Fruit>(new Fruit[] {new Banana(), new Apple()});

        var serializerSettings = new JsonSerializerSettings{ TypeNameHandling = TypeNameHandling.Auto };

        var json = JsonConvert.SerializeObject(list, serializerSettings);

        List<Fruit> fruitList = JsonConvert.DeserializeObject<List<Fruit>>(json, serializerSettings);
        List<Banana> bananaList = new List<Banana>();
        List<Apple> appleList = new List<Apple>();
        foreach (var fruit in fruitList)
        {
            if (fruit is Banana) bananaList.Add((Banana) fruit); 
            if (fruit is Apple) appleList.Add((Apple) fruit); 
        }
    }
}

你也可以使用一些linq来找到比foreach更容易的苹果/香蕉:

List<Banana> bananaList = fruitList.Where(f => f is Banana).Cast<Banana>().ToList();
List<Apple>  appleList  = fruitList.Where(f => f is Apple).Cast<Apple>().ToList();

或者,您可以使用此处讨论的转换器 使用 json.net 反序列化没有类型信息的多态 json 类

微生德泽
2023-03-14

在JSON.Net中,有< code>$type可以用来指定要反序列化为哪种类型:

string json = @"[
            {
                ""$type"":""Assembly.Namespace.banana"",
                ""monkey"":1
            },
            {
                ""$type"":""Assembly.Namespace.apple"",
                ""shape"":""round""
            }]";
 类似资料:
  • 我创建了这样一个熊猫系列:

  • 我正在尝试有一个通量通用转换器使用通用类型在Java 8。我把我的代码建立在这个答案的基础上。其思想基本上是实现这个特定的转换器->: 类型转换器->转换为我想要的任何类型。因此,我正在使用构造函数创建一个类型为的类,并返回一个方法。我想在调用上创建类似这样的多个条目:,但类类型不同。但它甚至对整数也不起作用。 当我使用此单元测试进行测试时,我得到错误:。

  • 作为一个简化的例子,考虑这个有两个字段的表。一个是字符串,另一个是XML。 Source=“MediaConversions” 现在我想查询该表,并将结果作为json,但也要一次性将XML转换为json。 导致 [{"Source":"媒体转换","OrderParameter":" 但我想把它转换成: [{"Source":"MediaConversion","OrderParameter":{

  • 我刚刚开始使用Retrofit2,我使用的API将所有有效的响应包装在一个“Response”对象中,如下所示。我需要告诉Retrofit只解析response中的值,而不实际将它们嵌套在另一个对象中。对于登录代码,我还面临着获取一个字符串的问题,我希望将其转换为实际的时间戳。 在上面仅有的两个实际值是: 我希望最终得到如下所示的东西。

  • 我有两个实体,它们使用一个主键互相引用,主键是一个实体的整数。我不确定我做这件事的方式是否正确。 下面是引用主键id为int的实体 下面是我们从上面的实体中将外键设置为Kmichango kandaMchango的实体。 这里是表单的一部分,我在这里提交了用户在jumuiya_michango_form.html中提供的数据 下面是我的控制器中用于链接到表单和发布数据的两个方法 在我提交表单后,我

  • org.springframework.beans.ConversionNotSupportedException:未能将类型“java.lang.long”的属性值转换为属性“card”所需的类型“card”;嵌套异常是java.lang.IllegalStateException:无法将类型“java.lang.Long”的值转换为属性“Card”所需的类型“Card”:找不到匹配的编辑器或转

  • 问题内容: 也许这很简单,但实际上我对Java 8功能不熟悉,不知道如何实现。我有一条包含以下文本的简单行: “密钥,名称” 并且我想将该行转换为String数组,并用逗号(,)分隔每个值,但是,我还想在返回最后一个数组之前修剪每个字段,所以我做了以下工作: 但是,这将返回Object []数组而不是String []数组。经过进一步检查,我可以确认内容实际上是String实例,但是数组本身是Ob

  • 也许这很简单,但实际上我对Java8特性一无所知,不知道如何实现这一点。我有一个简单的行,包含以下文本: “密钥,名称”