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

Json。NET反序列化或序列化json字符串,并将属性映射到运行时定义的不同属性名

杜祺
2023-03-14

我有以下JSON字符串:

{
    "values": {
        "details": {
            "property1": "94",
            "property2": "47",
            "property3": "32",
            "property4": 1
        },
        count: 4
    }
}     

我将把它映射到以下模型:

public class Details
{
    public string property1 { get; set; }
    public string property2 { get; set; }
    public string property3 { get; set; }
    public int property4 { get; set; }
}

public class Values
{
    public Details details { get; set; }
    public int count { get; set; }
}

public class RootObject
{
    public Values values { get; set; }
}

当反序列化这个JSON字符串时,我希望能够在运行时将这些属性名称映射到不同的名称,如下所示:

JsonConvert.DeserializeObject<RootObject>(jsonString);

例如,在反序列化过程中,我希望将“property1”的名称反序列化为“differen_property_name1”或“differen_property_name2”或“differen_property_name3”。因为我在运行时选择了新名称(我将“property1”名称改为的新名称),所以我无法使用使用JsonPropertyAttribute的解决方案,如下所示:

.NET NewtonSoft JSON反序列化映射到其他属性名称

上面问题的一个答案(Jack的答案)使用DefaultCompentResolver的继承,但在这种情况下似乎不起作用。

更新

后来,我需要序列化我从反序列化中得到的对象,并将属性映射到不同的属性名称,这些属性名称是在运行时定义的。我使用了布莱恩提议的相同方法来进行序列化:

我使用字典来映射我的新房产名称:

var map = new Dictionary<Type, Dictionary<string, string>>
{
    { 
        typeof(Details), 
        new Dictionary<string, string>
        {
            {"property1", "myNewPropertyName1"},
            {"property2", "myNewPropertyName2"},
            {"property3", "myNewPropertyName3"},
            {"property4", "myNewPropertyName4"}
        }
    }
};    

然后我使用Brian的DynamicMappingResolver来序列化对象,如下所示:

var settings = new JsonSerializerSettings
{
    ContractResolver = new DynamicMappingResolver(map)
};

var root = JsonConvert.SerializeObject(myObjectInstance, settings);            

共有3个答案

朱明知
2023-03-14

如果您不想使用自定义的ContractResolver来执行此操作。使用[JsonProperty(“”)查找属性名称的不同变体,并返回另一个属性,如下所示:

public class Details
{
    private string _property1;
    private string _property2;

    [JsonProperty("property1")]
    public string prop1 {get;set;}

    [JsonProperty("foo")]
    public string foo {get;set;}

    public string getProperty1 
    {
        get {_property1=prop1??foo;return _property1;}
        set{prop1=value;foo=value;}
    }

    [JsonProperty("property2")]
    public string prop2 {get;set;}

    [JsonProperty("bar")]
    public string bar {get;set;}

    public string getProperty2
    {
        get {_property2=prop2??bar;return _property2;}
        set {prop2=value;bar=value;}
    }
}

此处演示:https://dotnetfiddle.net/V17igc

储俊英
2023-03-14

为什么一步到位?为什么不反序列化到标准对象中,然后使用Automapper动态映射它们呢?

比如:

Mapper.Initialize(c =>
{
    c.ReplaceMemberName("property1 ", "differen_property_name1");
});
陈琪
2023-03-14

您可以使用自定义的合同解析程序来实现这一点。基本上,这与在您想要映射到不同JSON属性名称的每个类成员上放置一个[JsonProperty]属性是相同的,只是您可以通过解析程序以编程方式进行。在反序列化之前设置解析程序时,您可以将所需映射的字典传递给解析程序。

以下是自定义解析器代码的外观:

class DynamicMappingResolver : DefaultContractResolver
{
    private Dictionary<Type, Dictionary<string, string>> memberNameToJsonNameMap;

    public DynamicMappingResolver(Dictionary<Type, Dictionary<string, string>> memberNameToJsonNameMap)
    {
        this.memberNameToJsonNameMap = memberNameToJsonNameMap;
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty prop = base.CreateProperty(member, memberSerialization);
        Dictionary<string, string> dict;
        string jsonName;
        if (memberNameToJsonNameMap.TryGetValue(member.DeclaringType, out dict) && 
            dict.TryGetValue(member.Name, out jsonName))
        {
            prop.PropertyName = jsonName;
        }
        return prop;
    }
}

要使用解析器,首先构造一个字典

因此,例如,如果您的JSON看起来像这样(注意细节对象中属性的更改名称)...

{
    "values": {
        "details": {
            "foo": "94",
            "bar": "47",
            "baz": "32",
            "quux": 1
        },
        count: 4
    }
}

...如果你想把它映射到你问题中的类,你可以这样创建字典:

var map = new Dictionary<Type, Dictionary<string, string>>
{
    { 
        typeof(Details), 
        new Dictionary<string, string>
        {
            {"property1", "foo"},
            {"property2", "bar"},
            {"property3", "baz"},
            {"property4", "quux"}
        }
    }
};

最后一步是使用一个新的解析器实例设置序列化程序设置,为其提供刚刚构建的映射字典,然后将设置传递给JsonConvert。反序列化对象()

var settings = new JsonSerializerSettings
{
    ContractResolver = new DynamicMappingResolver(map)
};

var root = JsonConvert.DeserializeObject<RootObject>(json, settings);

这里有一个演示:https://dotnetfiddle.net/ULkB0J

 类似资料:
  • 下面是从外部方接收的JSON字符串。 问题是我不喜欢类中的类名和字段名。相反,我希望将其命名为,并且将从字段名称中删除,并给出正确的名称。 我可以将重命名为,但如果更改字段名(类中的),它将无法正确反序列化,并给我。我怎样才能克服这些呢?

  • 问题内容: 我有以下从外部方收到的JSON字符串。 我的映射类: 现在的问题是,我不喜欢的 类名 和 字段名 的类。相反,我希望它被命名,并且还希望从字段名称中删除并提供适当的名称。 我可以重命名为,但是如果我更改了字段名(在类中),它将无法正确地反序列化并提供给我。我该如何克服呢? 问题答案: Json.NET具有允许您指定JSON属性名称的名称,因此您的代码应为: 文档: 序列化属性

  • 问题内容: 我有一些具有各种属性的JSON,其中大多数是简单数据类型。但是,我在JSON中有一个属性,当我将其反序列化为C#类时,我只需要将其反序列化为字符串即可。 JSON示例: 除了将是有效的JSON对象外,“ json”对象没有任何设置结构。 因此,在上面的示例中,“ json”的值是一个JSON对象-但是当它反序列化时,我需要将它作为字符串。 因此,如果我的C#类是: 然后,如果我使用:

  • 问题内容: 使用Jackson 2,我正在寻找一种 通用的 方式将对象序列化为单个值(然后序列化它们,然后再填充该单个字段),而不必重复创建JsonSerializer / JsonDeserializer来处理每种情况。@JsonIdentityInfo批注非常接近,但由于我知道,它将始终对完整的子对象进行序列化,因此略微遗漏了该标记。 这是我想做的一个例子。给定的类: 我希望Order可以序列

  • 问题内容: 是否可能:在类中有一个字段,而在Jackson库中进行序列化/反序列化时却为其使用不同的名称? 例如,我有“ Coordiantes”类。 对于从JSON反序列化,希望具有以下格式: 但是当我序列化对象时,结果应该是这样的: 我试图通过在getter和setter上都应用注释(具有不同的值)来实现此目的: 但我有一个例外: org.codehaus.jackson.map.exc.Un

  • 问题内容: 我正在针对返回JSON数据的第三方API进行编程,但是格式可能有点奇怪。某些属性可以是一个对象(包含一个Id属性),也可以是一个字符串(它是该对象的ID)。例如,以下两个都是有效的: 和 我正在尝试使用JSON.net将其反序列化为强类型类,但到目前为止运气还不足。我最好的主意是将其序列化为两个属性,一个为字符串,另一个为对象,并为每个属性使用自定义JsonConverter以允许变量