C# Json.NET 使用根名称序列化对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16294963/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Json.NET serialize object with root name
提问by user2034092
In my web app I'm using Newtonsoft.Json and I have following object
在我的网络应用程序中,我使用的是 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;}
}
and I want serialize them with root name (class name). This is desired format using
我想用根名称(类名)序列化它们。这是使用所需的格式
{'MyCar':
{
'name': 'Ford',
'owner': 'John Smith'
}
}
I know that I can do that with anonymous object, but is any property or another way in Newtonsoft.Json library?
我知道我可以用匿名对象做到这一点,但是 Newtonsoft.Json 库中有任何属性或其他方式吗?
回答by Andrei
Use anonymous class
使用匿名类
Shape your model the way you want using anonymous classes:
使用匿名类以您想要的方式塑造您的模型:
var root = new
{
car = new
{
name = "Ford",
owner = "Henry"
}
};
string json = JsonConvert.SerializeObject(root);
回答by Newton Sheikh
string Json = JsonConvert.SerializeObject(new Car { Name = "Ford", Owner = "John Smith" }, Formatting.None);
for the root element use GlobalConfiguration.
对于根元素使用 GlobalConfiguration。
回答by I4V
You can easily create your own serializer
您可以轻松创建自己的序列化程序
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();
}
回答by Matthew Merryfull
I found an easy way to render this out... simply declare a dynamic object and assign the first item within the dynamic object to be your collection class...This example assumes you're using Newtonsoft.Json
我找到了一种简单的方法来渲染它...只需声明一个动态对象并将动态对象中的第一项分配为您的集合类...此示例假设您使用的是 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);
What you should end up with is something like this:
你最终应该是这样的:
{"myRoot":[{"firstName":"John", "lastName": "Citizen"}, {...}]}
回答by Radovan Jankovic
Well, you can at least tell Json.NET to include the type name: http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htm. Newtonsoft.Json.JsonSerializer jser = new Newtonsoft.Json.JsonSerializer();
jser.TypeNameHandling = TypeNameHandling.Objects;
好吧,您至少可以告诉 Json.NET 包含类型名称:http: //www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htm。Newtonsoft.Json.JsonSerializer jser = new Newtonsoft.Json.JsonSerializer();
jser.TypeNameHandling = TypeNameHandling.Objects;
The type will be included at the beginning in the "$type" property of the object.
该类型将包含在对象的“$type”属性的开头。
This is not exactly what you are looking for, but it was good enough for me when facing a similiar problem.
这不完全是您要找的东西,但是当我遇到类似的问题时,这对我来说已经足够了。
回答by Monkey Programmer
I hope this help.
我希望这会有所帮助。
//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="[email protected]"
};
var serializedObject = customer.JsonSerialize();
回答by gmuonio
[Newtonsoft.Json.JsonObject(Title = "root")]
public class TestMain
this is the only attrib you need to add to get your code working.
这是您需要添加才能使代码正常工作的唯一属性。
回答by jet_choong
A very simple approach for me is just to create 2 classes.
对我来说一个非常简单的方法就是创建 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; }
}
And when you going to do serialization:
当您要进行序列化时:
var classAList = new ClassAList();
//...
//assign some value
//...
var jsonString = JsonConvert.SerializeObject(classAList)
Lastly, you will see your desired result as the following:
最后,您将看到您想要的结果如下:
{
"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"
}
]
}
Hope this helps!
希望这可以帮助!
回答by user2440841
Sorry, my english is not that good. But i like to improve the upvoted answers. I think that using Dictionary is more simple and clean.
对不起,我的英语不是很好。但我喜欢改进赞成的答案。我认为使用 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; }
}
This code generate the following json (This is desired format)
此代码生成以下 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
]
]
}
}
回答by prusswan
Writing a custom JsonConverteris another approach mentioned in similar questions. However, due to nature of how JsonConverteris designed, using that approach for this question is tricky, as you need to be careful with the WriteJsonimplementation to avoid getting into infinite recursion: JSON.Net throws StackOverflowException when using [JsonConvert()].
编写自定义JsonConverter是类似问题中提到的另一种方法。但是,由于JsonConverter设计方式的性质,对这个问题使用这种方法很棘手,因为您需要小心WriteJson实现以避免陷入无限递归:JSON.Net 在使用 [JsonConvert()] 时抛出 StackOverflowException。
One possible implementation:
一种可能的实现:
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();
}

