更改对象中属性的名称,该属性已从 C# 中的 JSON 字符串反序列化



>我的反序列化对象的名称有问题,我想返回它。

目前,我正在编写一个 Web 服务,它从另一个 Web 服务请求数据,然后将此数据返回到应用程序。

例:

public class UserController
{
    public HttpResponseMessage GetUser()
    {
        // Get Data from WebService
        string jsonString = @"{'key': 'A45', 'field1': 'John', 'field2': 'Doe', address{'field3': 'HelloWorld Ave.', 'field4': 'Somewhere'}}";
        // Make Object from JSON-String
        User user = JsonConvert.DeserializeObject<User>(jsonString);
        // Return Object to Application
        return Request.CreateResponse(HttpStatusCode.OK, user);
    }
}
public class User
{
    [JsonProperty("key")]
    public string Key { get; set; }
    [JsonProperty("field1")]
    public string FirstName { get; set; }
    [JsonProperty("field2")]
    public string LastName { get; set; }
    [JsonProperty("address")]
    public Address Address { get; set; }
}
public class Address
{
    [JsonProperty("field3")]
    public string Street { get; set; }
    [JsonProperty("field4")]
    public string City { get; set; }
}

目前为止,一切都好。我的 Web 服务创建对象"用户"并将其返回到应用程序。

现在我的问题:

返回的 JSON 字符串将字段名称更改回其原始名称。

而不是:

"{'key': 'A45', 'field1': 'John', 'field2': 'Doe', Address {'Street': 'HelloWorld Ave.', 'City': 'Somewhere'}}"

我得到:

"{'key': 'A45', 'field1': 'John', 'field2': 'Doe', Address {'Street': 'HelloWorld Ave.', 'City': 'Somewhere'}}"

我知道 JsonProperty 中的 PropertyName 不区分大小写,所以我可以用大写的"K"写[JsonProperty("Key")],返回的 Json-String 将包含大写的"K"。

但是我的田地呢?有什么方法可以将"字段1"更改为"名字",将"字段2"更改为"姓氏"?

编辑 1 - 2015-01-28:向示例添加了更多代码。

我建议执行 2 个步骤

  1. 按原样(反)序列化 DTO(数据传输对象)
  2. 实现一个程序集层,您可以在其中控制域对象的创建。

在您的情况下,DTO和DomainModel之间似乎是1:1的关系,只是具有不同的属性名称 - 因此您只需要以这种方式进行投影。我可以强烈推荐自动映射器投影,或者如果它是嵌套的自动映射器嵌套投影。

这里最大的优势是您可以将整个域层与外部服务分离,因此即使您的 Web 服务被破坏/更改,也不会影响您的业务逻辑。

@stefankmitph和@nhaberl的答案都是很好的答案,但最终我使用了略有不同的技术。

我的两个类现在都有私有字段,用于将 JSON 字符串的值设置为公共字段。

私有字段获取传入 JSON 字符串的属性名称,公共字段获取传出 JSON 字符串的属性名称:

public class User
{
    #region private
    [JsonProperty("key")]
    private string _Key { set { Key = value; } }
    [JsonProperty("field1")]
    private string _FirstName { set { FirstName = value; } }
    [JsonProperty("field2")]
    private string _LastName { set { LastName = value; } }
    [JsonProperty("address")]
    private Address _Address { set { Address = value; } }
    #endregion

    #region public
    [JsonProperty("Key")]
    public string Key { get; private set; }
    [JsonProperty("FirstName")]
    public string FirstName { get; private set; }
    [JsonProperty("LastName")]
    public string LastName { get; private set; }
    [JsonProperty("Address")]
    public Address Address { get; private set; }
    #endregion
}
public class Address
{
    #region private
    [JsonProperty("field3")]
    private string _Street { set { Key = value; } }
    [JsonProperty("field4")]
    private string _City { set { FirstName = value; } }
    #endregion

    #region public
    [JsonProperty("Street")]
    public string Street { get; private set; }
    [JsonProperty("City")]
    public string City { get; private set; }
    #endregion
}

示例输出:

"{'Key': 'A45', 'FirstName': 'John', 'LastName': 'Doe', Address {'Street': 'HelloWorld Ave.', 'City': 'Somewhere'}}"

使用此方法,我还可以将所有数据从无错误类获取到主类:

public class User
{
    #region private
    // Other fields, see above. \
    [JsonProperty("address")]
    private Address _Address 
    { 
        set 
        { 
            City = value.City;
            Street = value.Street;
        } 
    }
    #endregion

    #region public
    // Other fields, see above. \
    [JsonProperty("City")]
    public string City { get; private set; }
    [JsonProperty("Street")]
    public string Street { get; private set; }
    #endregion
}
public class Address
{
    // Address fields. See above.
}

示例输出:

"{'Key': 'A45', 'FirstName': 'John', 'LastName': 'Doe', 'Street': 'HelloWorld Ave.', 'City': 'Somewhere'}"

通过编写自己的序列化程序并向属性添加自定义属性,可以强制序列化程序在序列化回 JSON 时采用自定义名称。

public class JsonSerializeProperty : Attribute
{
    public string PropertyName { get; set; }
}
// derive from JsonConverter and override WriteJson (serialize) 
// and ReadJson (deserialize)
// note: i have not implemented CanConvert
public class CustomUserSerializer : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var user = value as User;
        if(user == null)
            throw new NullReferenceException("user");
        var properties = user.GetType().GetProperties();
        writer.WriteStartObject();
        foreach (var property in properties)
        {
            // get the attribute assigned to the property [JsonSerializeProperty]
            object customAttributes = property.GetCustomAttributes(typeof(JsonSerializeProperty), false).SingleOrDefault();
            JsonSerializeProperty attribute = customAttributes as JsonSerializeProperty;
            if(attribute != null)
            {
                // JsonSerializeProperty 
                string propertyName = attribute.PropertyName;
                // just write new property name and value
                writer.WritePropertyName(propertyName);
                writer.WriteValue(property.GetValue(value, new object[] {}));
            }
        }
        writer.WriteEndObject();
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // just map every JProperty from the Json string to the  
        // JsonProperty of the user class. I know this is kind of ugly... but it may serve your purpose
        JObject jsonObject = JObject.Load(reader);
        List<JProperty> properties = jsonObject.Properties().ToList();
        // create an instance of User to assign the values of the
        // Json string 
        object instance = Activator.CreateInstance(objectType);
        // loop through the user properties and get the 
        // JsonProperty customattribute. then set the value of the JProperty
        PropertyInfo[] objectProperties = objectType.GetProperties();
        foreach (var objectProperty in objectProperties)
        {
            var customAttribute = objectProperty.GetCustomAttributes(typeof(JsonPropertyAttribute), false).SingleOrDefault();
            JsonPropertyAttribute attribute = customAttribute as JsonPropertyAttribute;
            if (attribute != null)
            {
                JProperty jsonProperty = properties.SingleOrDefault(prop => prop.Name == attribute.PropertyName);
                if (jsonProperty != null)
                {
                    objectProperty.SetValue(instance, jsonProperty.Value.ToString(), new object[] {});                        
                }
            }
        }
        return instance;
        // {
        //    _Key = "A45",
        //    _FirstName = "John",
        //    _LastName = "Doe"
        // }
    }
    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }
}
[JsonConverter(typeof(CustomUserSerializer))]
public class User
{
    [JsonProperty(PropertyName = "key")]
    [JsonSerializeProperty(PropertyName = "_Key")]
    public string Key { get; set; }
    [JsonProperty("field1")]
    [JsonSerializeProperty(PropertyName = "_FirstName")]
    public string FirstName { get; set; }
    [JsonProperty("field2")]
    [JsonSerializeProperty(PropertyName = "_LastName")]
    public string LastName { get; set; }
}

相关内容

  • 没有找到相关文章

最新更新