我如何获得Json.NET将Int32转换为URI - c#

在C#代码中,我想使用我设计的Int32属性-作为int,但是当使用Json.NET转换为Json时,我希望将它们序列化为URI,因此我不必映射所有内容我将模型转换为另一个模型,仅用于json输出。例如简化模型:

public class Order
{
    public int? AccountID { get; set; }
    public int ProductID { get; set; }
    public decimal Total { get; set; }
}

我希望这样渲染:

{ "accountUri": "/account/123", "productUri": "/product/456", "total": 789.01 }

请注意大小写和属性重命名已更改。

如果AccountID为null,则json必须呈现为以下形式:

{ "productUri": "/product/456", "total": 789.01 }

在C#代码中,我仍然希望像使用普通int一样使用属性-因此,我正在考虑使用int运算符覆盖。

我不想在模型属性上使用属性,但是很高兴为Int32使用包装器类,并且不介意在需要时在包装器类上使用属性。

以下代码是回答问题的一种合理方法,但是您能理解以下要点:

    public class Order
    {
        public AccountIdentifier AccountID { get; set; }
        public ProductIdentifier ProductID { get; set; }
        public decimal Total { get; set; }
    }

    public abstract class IdentifierBase
    {
        private readonly string _uriPrefix;
        private int? _value;

        protected IdentifierBase(string uriPrefix, int? value)
        {
            _uriPrefix = uriPrefix;
            _value = value;
        }

        public override string ToString()
        {
            if (_value.HasValue)
                return _uriPrefix + _value.Value;
            return null;
        }

        // insert int operator overrides here.
    }

    public class AccountIdentifier : IdentifierBase
    {
        public AccountIdentifier(int? value)
            : base("/account/", value)
        {
        }
    }

    public class ProductIdentifier : IdentifierBase
    {
        public ProductIdentifier(int? value)
            : base("/product/", value)
        {
        }
    }

    [Test]
    public void JsonConvert()
    {
        var order = new Order
        {
            AccountID = new AccountIdentifier(123),
            ProductID = new ProductIdentifier(456),
            Total = 789.01M
        };

        using (var stringWriter = new StringWriter())
        {
            var writer = new JsonTextWriter(stringWriter) {Formatting = Formatting.None};
            var settings = new JsonSerializerSettings();
            var serializer = JsonSerializer.Create(settings);

            // Camel case the properties.
            serializer.ContractResolver = new CamelCasePropertyNamesContractResolver();

            serializer.Serialize(writer, order);
            writer.Flush();
            var json = stringWriter.GetStringBuilder().ToString();
            Console.Write(json);
        }
    }

输出:

{"accountID":{},"productID":{},"total":789.01}

三个问题:

如何将“ accountID”重命名为“ accountUri”(以及将“ productID”重命名为“ productUri”)?
如何呈现这些属性的值(用包装器类的ToString()结果替换“ {}”)?
如果该属性为空,如何将其完全删除?

谢谢。

编辑:尽管为每种模型编写转换器需要进行大量工作,但确实节省了编写两个映射器的工作。这是我的概念验证测试:

    [TestFixture]
    public class MyPoC
    {
        public class OrderJsonConverter : JsonConverter
        {
            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                writer.WriteStartObject();

                var order = value as Order;

                if (order.AccountID.HasValue)
                {
                    writer.WritePropertyName("accountUri");
                    serializer.Serialize(writer, "/account/" + order.AccountID);
                }

                writer.WritePropertyName("productUri");
                serializer.Serialize(writer, "/product/" + order.ProductID);

                writer.WritePropertyName("total");
                serializer.Serialize(writer, order.Total);

                writer.WriteEndObject();
            }

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                var order = new Order();

                var jsonObject = JObject.Load(reader);
                order.AccountID = jsonObject.GetNullableIntFromUri("accountUri");
                order.ProductID = jsonObject.GetIntFromUri("productUri");
                order.Total = jsonObject["total"].Value<decimal>();
                return order;
            }

            public override bool CanConvert(Type objectType)
            {
                return typeof(Order).IsAssignableFrom(objectType);
            }
        }

        [Test]
        public void JsonConvert_Is_Successful()
        {
            var order = new Order
            {
                AccountID = 123,
                ProductID = 456,
                Total = 789.01M
            };

            var json = JsonConvert.SerializeObject(order, Formatting.None, new OrderJsonConverter());
            Console.WriteLine(json);

            var deserialized = JsonConvert.DeserializeObject<Order>(json, new OrderJsonConverter());
            Console.WriteLine("AccountID: {0}", deserialized.AccountID);
            Console.WriteLine("ProductID: {0}", deserialized.ProductID);
            Console.WriteLine("Total: {0}", deserialized.Total);
        }
    }
}

public static class JObjectExtensions
{
    public static int GetIntFromUri(this JObject jsonObject, string propertyName)
    {
        var id = jsonObject.GetNullableIntFromUri(propertyName);
        return id.Value;
    }

    public static int? GetNullableIntFromUri(this JObject jsonObject, string propertyName)
    {
        var uri = jsonObject[propertyName].ToObject<string>();
        var s = Regex.Replace(uri, @".*/(\d+)$", "$1");
        int id;
        if (int.TryParse(s, out id))
        {
            return id;
        }
        return null;
    }
}

输出:

{"accountUri":"/account/123","productUri":"/product/456","total":789.01}
AccountID: 123
ProductID: 456
Total: 789.01

额外的工作将是验证uri的正确性,而不仅仅是通用的“从uri的末尾撕掉ID”。

参考方案

由于您已经决定考虑使用适配器模式,因此以下是带有测试的示例实现:

[TestFixture]
public class When_serializing_Order
{
    [SetUp]
    public void SetUp()
    {
        JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            NullValueHandling = NullValueHandling.Ignore
        };
    }

    [TestCase(123, 456, 789.01, "{\"accountUri\":\"/account/123\",\"productUri\":\"/product/456\",\"total\":789.01}")]
    [TestCase(null, 456, 789.01, "{\"productUri\":\"/product/456\",\"total\":789.01}")]
    public void Should_render_exact_json(int? accountId, int productId, decimal total, string expectedJson)
    {
        var order = new Order
        {
            AccountID = accountId,
            ProductID = productId,
            Total = total
        };
        string jsonOrder = JsonConvert.SerializeObject(new OrderAdapter(order));
        Assert.That(jsonOrder, Is.EqualTo(expectedJson));
    }
}

public class Order
{
    public int? AccountID { get; set; }
    public int ProductID { get; set; }
    public decimal Total { get; set; }
}

public class OrderAdapter
{
    private readonly Uri _accountUri;
    private readonly Uri _productUri;
    private readonly decimal _total;

    public OrderAdapter(Order order)
    {
        _accountUri = order.AccountID != null ? CreateRelativeUri("account", order.AccountID.Value) : null;
        _productUri = CreateRelativeUri("product", order.ProductID);
        _total = order.Total;
    }

    public Uri AccountUri { get { return _accountUri; } }
    public Uri ProductUri { get { return _productUri; } }
    public decimal Total { get { return _total; } }

    private Uri CreateRelativeUri(string resourceType, int id)
    {
        return new Uri(String.Format("/{0}/{1}", resourceType, id), UriKind.Relative);
    }
}

如果您有任何疑问,请发表评论,我将为需要进一步解释的内容添加注释。

如何从php中获取datatables jQuery插件的json数据 - php

我是PHP的新手,正在尝试使用Datatables jQuery插件。我知道我必须从.php文件中获取数据,然后在数据表中使用它,但是我似乎无法通过ajax将其传递给数据表。我设法从数据库中获取数据,并对其进行json编码,但是后来我不知道如何在我的index.php文件中调用它,并在其中显示它。我究竟做错了什么?这是我的代码:HTML(已编辑): <…

当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java

我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…

改造正在返回一个空的响应主体 - java

我正在尝试使用Retrofit和Gson解析一些JSON。但是,我得到的响应机构是空的。当我尝试从对象中打印信息时,出现NullPointerException。我确保URL正确,并且我也确保POJO也正确。我正在使用jsonschema2pojo来帮助创建POJO类。这是我要解析的JSON{ "?xml": { "@versi…

每个文件合并后添加换行 - python

我有很多类似以下内容的JSON文件:例如。1.json{"name": "one", "description": "testDescription...", "comment": ""} test.json{"name"…

Json到php,json_decode返回NULL - php

我正在用PHP进行JSON解析器的一些API,用于存储有关遗产的信息。我在解析时遇到问题,因为它返回的是NULL值而不是数组或对象。简单的JSON代码可以很好地解析,但是可以这样:{"success":true,"totalCount":1,"data":[{"id":99694…