【问题标题】:Json.NET serialize object with root nameJson.NET 使用根名称序列化对象
【发布时间】:2013-04-24 01:58:39
【问题描述】:

在我的网络应用程序中,我使用的是 Newtonsoft.Json,并且我有以下对象

[Newtonsoft.Json.JsonObject(Title = "MyCar")]
public class Car
{
    [Newtonsoft.Json.JsonProperty(PropertyName = "name")]
    public string Name{get;set;}

    [Newtonsoft.Json.JsonProperty(PropertyName = "owner")]
    public string Owner{get;set;}
}

我想用根名称(类名)对它们进行序列化。这是使用

的所需格式
{'MyCar':
 {
   'name': 'Ford',
   'owner': 'John Smith'
 }
}

我知道我可以使用匿名对象来做到这一点,但是 Newtonsoft.Json 库中有任何属性或其他方式吗?

【问题讨论】:

    标签: c# asp.net .net json json.net


    【解决方案1】:

    使用匿名类

    使用匿名类以您想要的方式塑造您的模型:

    var root = new 
    { 
        car = new 
        { 
            name = "Ford", 
            owner = "Henry"
        }
    };
    
    string json = JsonConvert.SerializeObject(root);
    

    【讨论】:

    • 如果我在具有 JsonConvert.SerializeObject 的方法中将对象作为输入,我该如何实现呢? public void SendMessage(object someObject) { JsonConvert.SerializeObject(someObject); } 在这种情况下,每次根元素都是“someObject”,而不是所需的名称。
    • 在哪里可以找到“RootFormatter”类?我必须在此处包含哪个命名空间?
    • @alok_dida 好像很老了,我现在找不到 - 我会删除这部分。谢谢
    【解决方案2】:

    我找到了一种简单的方法来呈现它...只需声明一个动态对象并将动态对象中的第一项分配为您的集合类...此示例假设您使用的是 Newtonsoft.Json

    private class YourModelClass
    {
        public string firstName { get; set; }
        public string lastName { get; set; }
    }
    
    var collection = new List<YourModelClass>();
    
    var collectionWrapper = new {
    
        myRoot = collection
    
    };
    
    var output = JsonConvert.SerializeObject(collectionWrapper);
    

    你最终应该是这样的:

    {"myRoot":[{"firstName":"John", "lastName": "Citizen"}, {...}]}
    

    【讨论】:

    • 如果我们返回字符串...结果显示额外的引号...应该删除...通过此链接forums.asp.net/t/…
    • 这行得通。我一直在寻找这样的东西,以避免必须声明一个包装器 RootObject 类。
    • 什么是myRoot
    • @Delfino myRoot 只是一个任意字符串,你可以在那里指定任何你想要的东西。
    • 这为我提供了一个与 JsonConfig 兼容的列表,以便在进行少量查找和替换编辑后从 JsonConfig 配置文件 (settings.conf) 中读入集合。如果我需要将整个事情反复自动化,我可以将它正则表达式到这种形式。这就是我在 JsonConfig 设置文件中所追求的:TestsToRun:["MySpecFlowXunitTest1.dll","MySpecFlowXunitTestOther.dll","MySpecFlowXunitTestYetAnother.dll"] 然后这条 C# 行使用 JsonConfig 读取它们: List allowedTestsList = Config .Global.TestsToRun;
    【解决方案3】:

    您可以轻松创建自己的序列化程序

    var car = new Car() { Name = "Ford", Owner = "John Smith" };
    string json = Serialize(car);
    

    string Serialize<T>(T o)
    {
        var attr = o.GetType().GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute;
    
        var jv = JValue.FromObject(o);
    
        return new JObject(new JProperty(attr.Title, jv)).ToString();
    }
    

    【讨论】:

      【解决方案4】:

      对不起,我的英语不太好。但我喜欢改进被赞成的答案。 我认为使用 Dictionary 更简单干净。

      class Program
          {
              static void Main(string[] args)
              {
                  agencia ag1 = new agencia()
                  {
                      name = "Iquique",
                      data = new object[] { new object[] {"Lucas", 20 }, new object[] {"Fernando", 15 } }
                  };
                  agencia ag2 = new agencia()
                  {
                      name = "Valparaiso",
                      data = new object[] { new object[] { "Rems", 20 }, new object[] { "Perex", 15 } }
                  };
                  agencia agn = new agencia()
                  {
                      name = "Santiago",
                      data = new object[] { new object[] { "Jhon", 20 }, new object[] { "Karma", 15 } }
                  };
      
      
                  Dictionary<string, agencia> dic = new Dictionary<string, agencia>
                  {
                      { "Iquique", ag1 },
                      { "Valparaiso", ag2 },
                      { "Santiago", agn }
                  };
      
                  string da = Newtonsoft.Json.JsonConvert.SerializeObject(dic);
      
                  Console.WriteLine(da);
                  Console.ReadLine();
              }
      
      
          }
      
          public class agencia
          {
              public string name { get; set; }
              public object[] data { get; set; }
          }
      

      此代码生成以下json(这是所需的格式)

      {  
         "Iquique":{  
            "name":"Iquique",
            "data":[  
               [  
                  "Lucas",
                  20
               ],
               [  
                  "Fernando",
                  15
               ]
            ]
         },
         "Valparaiso":{  
            "name":"Valparaiso",
            "data":[  
               [  
                  "Rems",
                  20
               ],
               [  
                  "Perex",
                  15
               ]
            ]
         },
         "Santiago":{  
            "name":"Santiago",
            "data":[  
               [  
                  "Jhon",
                  20
               ],
               [  
                  "Karma",
                  15
               ]
            ]
         }
      }
      

      【讨论】:

      • 非常整洁,正是我想要的
      【解决方案5】:
      string Json = JsonConvert.SerializeObject(new Car { Name = "Ford", Owner = "John Smith" }, Formatting.None);
      

      对于根元素,使用 GlobalConfiguration。

      【讨论】:

        【解决方案6】:

        对我来说一个非常简单的方法就是创建 2 个类。

        public class ClassB
        {
            public string id{ get; set; }
            public string name{ get; set; }
            public int status { get; set; }
            public DateTime? updated_at { get; set; }
        }
        
        public class ClassAList
        {
            public IList<ClassB> root_name{ get; set; } 
        }
        

        当你要进行序列化时:

        var classAList = new ClassAList();
        //...
        //assign some value
        //...
        var jsonString = JsonConvert.SerializeObject(classAList)
        

        最后,你会看到你想要的结果如下:

        {
          "root_name": [
            {
              "id": "1001",
              "name": "1000001",
              "status": 1010,
              "updated_at": "2016-09-28 16:10:48"
            },
            {
              "id": "1002",
              "name": "1000002",
              "status": 1050,
              "updated_at": "2016-09-28 16:55:55"
            }
          ]
        }
        

        希望这会有所帮助!

        【讨论】:

          【解决方案7】:

          好吧,您至少可以告诉 Json.NET 包含类型名称:http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htmNewtonsoft.Json.JsonSerializer jser = new Newtonsoft.Json.JsonSerializer(); jser.TypeNameHandling = TypeNameHandling.Objects;

          类型将包含在对象的“$type”属性的开头。

          这不是您要找的,但在遇到类似问题时对我来说已经足够了。

          【讨论】:

            【解决方案8】:

            编写自定义JsonConverter 是类似问题中提到的另一种方法。但是,由于JsonConverter 的设计方式的性质,使用这种方法解决这个问题很棘手,因为您需要小心WriteJson 实现以避免陷入无限递归:JSON.Net throws StackOverflowException when using [JsonConvert()]

            一种可能的实现方式:

            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                //JToken t = JToken.FromObject(value); // do not use this! leads to stack overflow
                JsonObjectContract contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(value.GetType());
            
                writer.WriteStartObject();
                writer.WritePropertyName(value.GetType().Name);
                writer.WriteStartObject();
                foreach (var property in contract.Properties)
                {
                    // this removes any property with null value
                    var propertyValue = property.ValueProvider.GetValue(value);
                    if (propertyValue == null) continue;
            
                    writer.WritePropertyName(property.PropertyName);
                    serializer.Serialize(writer, propertyValue);
                    //writer.WriteValue(JsonConvert.SerializeObject(property.ValueProvider.GetValue(value))); // this adds escaped quotes
                }
                writer.WriteEndObject();
                writer.WriteEndObject();
            }
            

            【讨论】:

              【解决方案9】:

              希望对你有所帮助。

              //Sample of Data Contract:
              
              [DataContract(Name="customer")]
              internal class Customer {
                [DataMember(Name="email")] internal string Email { get; set; }
                [DataMember(Name="name")] internal string Name { get; set; }
              }
              
              //This is an extension method useful for your case:
              
              public static string JsonSerialize<T>(this T o)
              {
                MemoryStream jsonStream = new MemoryStream();
                var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T));
                serializer.WriteObject(jsonStream, o);
              
                var jsonString = System.Text.Encoding.ASCII.GetString(jsonStream.ToArray());
              
                var props = o.GetType().GetCustomAttributes(false);
                var rootName = string.Empty;
                foreach (var prop in props)
                {
                  if (!(prop is DataContractAttribute)) continue;
                  rootName = ((DataContractAttribute)prop).Name;
                  break;
                }
                jsonStream.Close();
                jsonStream.Dispose();
              
                if (!string.IsNullOrEmpty(rootName)) jsonString = string.Format("{{ \"{0}\": {1} }}", rootName, jsonString);
                return jsonString;
              }
              
              //Sample of usage
              
              var customer = new customer { 
              Name="John",
              Email="john@domain.com"
              };
              var serializedObject = customer.JsonSerialize();
              

              【讨论】:

                【解决方案10】:
                [Newtonsoft.Json.JsonObject(Title = "root")]
                public class TestMain
                

                这是使代码正常工作所需添加的唯一属性。

                【讨论】:

                  猜你喜欢
                  • 2023-03-15
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多