C#中的Json操作

随着JSON越来越多的应用到IT领域,C#中再也不是XML一家独占的情况了。熟练的解析和构建JSON也是必备技能。目前我正在参与的ArcGIS Earth产品,其工作区的保存格式以及软件中的传输格式都是使用JSON。就在此分享一些浅显的经验吧。

工欲善其事必先利其器,对于C#一般使用Newtonsoft.Json就行了,如果使用python则用json,但对于C++,由于许可和效率的问题,选择会很多,对于开源软件,我比较推荐Jsoncpp。

基础使用

对于一般的类或者对象,使用JsonConvert.SerializeObject(yourObject)或者
JsonConvert.DeserializeObject<T>(jsonString)就行。示例如下:

using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace AboutJson
{
    public enum Country
    {
        CN,
        EN,
        US
    }
    public class Family 
    {
        public Country Country { set; get; }
        public string Dad { set; get; }
        public string Mum { set; get; }
        public List<string> Children { set; get; }
    }

    class Program
    {
        static private string TestSerializeObject(Family f)
        {
            return JsonConvert.SerializeObject(f);
        }

        static private Family TestDeserializeObject(string familyJson)
        {
            return JsonConvert.DeserializeObject<Family>(familyJson);
        }
        static void Main(string[] args)
        {
            Family f = new Family {
                Country = Country.US,
                Dad = "Mr Brown",
                Mum = "Mrs Brown",
                Children = new List<string>{"Lily", "Lucy"} };

            // The result will be
            // { "Country":2,"Dad":"Mr Brown","Mum":"Mrs Brown","Children":["Lily","Lucy"]}
            // But sometimes we need country like this : "Country" : "US"
            string familyJson = TestSerializeObject(f);

            Family f1 = TestDeserializeObject(familyJson);
        }
    }
}

但是有时候我们有一些特殊的需求,例如,某些字段在转换为Json的时候不输出,枚举需要转换为字符串而不是数字,某些字段的键值需要自定义和变量名不相同。。。

这时候,在不修改原始对象的情况下,最直接的办法是自己手动来构建和解析Json字符串。

其中涉及到的内容为,JObject(JToken,JArray)和基础数据类型的转换。示例如下:

        static private string ConstructJsonManually(Family f)
        {
            JObject familyObj = new JObject();
            JArray childrenObj = new JArray();
            familyObj["Dad"] = f.Dad;
            familyObj[nameof(Family.Mum)] = f.Mum;
            familyObj[nameof(Country)] = f.Country.ToString();
            foreach(var child in f.Children)
            {
                childrenObj.Add(child);
            }
            familyObj[nameof(f.Children)] = childrenObj;
            return familyObj.ToString(Formatting.None);
        }

        static private Family ParseJsonManually(string familyJson)
        {
            Family f = new Family();
            Country country = Country.CN;
            JObject familyObj = JObject.Parse(familyJson);
            if(familyObj[nameof(Country)] != null)
            {
                Enum.TryParse(familyObj[nameof(Country)].ToString(), true, out country);
                f.Country = country;
            }

            if(familyObj[nameof(Family.Dad)] != null)
            {
                f.Dad = familyObj[nameof(Family.Dad)].ToString();
            }

            if(familyObj[nameof(Country)] != null)
            {
                f.Mum = familyObj[nameof(Family.Mum)].ToString();
            }

            if(familyObj[nameof(Family.Children)] != null)
            {
                JArray childrenObj = (JArray)familyObj[nameof(Family.Children)];
                f.Children = new List<string>();
                foreach(var child in childrenObj)
                {
                    f.Children.Add(child.ToString());
                }
            }
            return f;
        }

调用结果是:

            // The result will be 
            // { "Dad":"Mr Brown","Mum":"Mrs Brown","Country":"US","Children":["Lily","Lucy"]
            string familyJsonManual = ConstructJsonManually(f);

            Family f2 = ParseJsonManually(familyJsonManual);

进阶用法

如果觉得手动构建解析工作量大,后期不好维护,并且有权限修改原始的类,则可以使用一些进阶的用法了。如JsonSerializerSettingsJsonProperty,但是这儿,我对此不做过多介绍,对于高阶使用,查阅第一手的官方文档更加重要。

我在这儿举三个常用情况的例子吧。输出的时候修改键值,输出字符串形式的枚举,选择性的输出某些字段。

    [JsonObject(MemberSerialization.OptOut)]
    public class FamilyEx
    {
        [JsonConverter(typeof(StringEnumConverter))]
        public Country Country { set; get; }
        [JsonProperty(PropertyName = "Father")]
        public string Dad { set; get; }
        [JsonIgnore]
        public string Mum { set; get; }
        public List<string> Children { set; get; }
    }

    // The result will be 
    // { "Country":"US","Father":"Mr Brown","Children":["Lily","Lucy"]}
    string familyJsonEx = JsonConvert.SerializeObject(fEx);

其中使用[JsonObject(MemberSerialization.OptOut)][JsonIgnore]来选择性输出。
使用[JsonConverter(typeof(StringEnumConverter))]来以字符串输出枚举值。
使用[JsonProperty(PropertyName = "Father")]将键值由Dad修改为Father

结语

更个性化定制的内容,建议查阅第一手官方文档。消除隐患。C#中处理Json还是很方便的,但是由于Json格式的多样性和用户输入的不确定性,请使用try catch来捕获和判断异常,以便log和给出人性化的用户提示。

完整代码,见GitHub

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值