Khi sử dụng Json.Net, tôi hiểu cách lấy thuộc tính $ type vào json được kết xuất, nhưng có cách nào để thay đổi tên trường đó không? Tôi cần sử dụng "__type" thay vì "$ type".
Trả lời
Có vẻ như mã này được mã cứng là public const string TypePropertyName = "$type";
trong số Newtonsoft.Json.Serialization.JsonTypeReflector
thật không may là lớp tĩnh bên trong.
Tôi cần bản thân mình và điều duy nhất tôi có thể nghĩ là có phiên bản sửa đổi tùy chỉnh của json.net. Đó là tất nhiên là một pita lớn.
Thật không may, tôi đã hoàn toàn từ bỏ con đường tôi đã đi xuống vì Json.Net khó sử dụng như thế nào trong nhiều trường hợp. Đây chỉ là một ví dụ. –
Tôi là chính tôi đang tìm kiếm cách tôi ở phía máy chủ, được viết i C# và sử dụng Json.NET, có thể deserialize JSON được gửi từ một ứng dụng Android bằng cách sử dụng Jackson. Trong Jackson tôi có thể thiết lập để sử dụng "$ loại", nhưng nó không hoạt động anyway. – Ted
http://json.codeplex.com/workitem/22429
"Tôi thà giữ $ gõ cứng mã hoá và nhất quán."
Phù hợp với những gì tôi tự hỏi?
http://json.codeplex.com/workitem/21989
Tôi thà không - Tôi nghĩ rằng đây là quá cụ thể đối với tôi và tôi không muốn đi quá nhiệt tình với các thiết lập. Tại một số điểm, tôi có thể sẽ thực hiện điều này - http://json.codeplex.com/workitem/21856 - cho phép mọi người đọc/ghi có thuộc tính meta trong JSON và bạn có thể reimplement xử lý tên kiểu với tên thuộc tính mới. Tùy chọn khác chỉ là sửa đổi mã nguồn cho chính bạn để có tên thuộc tính đó.
Đây là giải pháp của tôi ...
json.Replace("\"$type\": \"", "\"type\": \"");
Giải pháp của bạn thật tuyệt vời!^_^ –
Xem thêm: https://github.com/JamesNK/Newtonsoft.Json/issues/1331 – manuc66
Chúng tôi đã có một nhu cầu cho điều này vì vậy tôi đã tạo ra một JsonReader tùy chỉnh. Chúng tôi đang sử dụng phần còn lại trong các dịch vụ web MS của chúng tôi với các mô hình dữ liệu phức tạp và cần thiết để thay thế thuộc tính "__type" bằng "$ type".
class MSJsonReader : JsonTextReader
{
public MSJsonTextReader(TextReader reader) : base(reader) { }
public override bool Read()
{
var hasToken = base.Read();
if (hasToken && base.TokenType == JsonToken.PropertyName && base.Value != null && base.Value.Equals("__type"))
base.SetToken(JsonToken.PropertyName, "$type");
return hasToken;
}
}
Đây là cách chúng tôi sử dụng.
using(JsonReader jr = new MSJsonTextReader(sr))
{
JsonSerializer s = new JsonSerializer();
s.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
s.NullValueHandling = NullValueHandling.Ignore;
s.TypeNameHandling = TypeNameHandling.Auto; // Important!
s.Binder = new MSRestToJsonDotNetSerializationBinder("Server.DataModelsNamespace", "Client.GeneratedModelsNamespace");
T deserialized = s.Deserialize<T>(jr);
return deserialized;
}
Đây là MSRestToJsonDotNetSerializationBinder hoàn thành khả năng tương thích giữa phần còn lại MS và Json.Net.
class MSRestToJsonDotNetSerializationBinder : System.Runtime.Serialization.SerializationBinder
{
public string ServiceNamespace { get; set; }
public string LocalNamespace { get; set; }
public MSRestToJsonDotNetSerializationBinder(string serviceNamespace, string localNamespace)
{
if (serviceNamespace.EndsWith("."))
serviceNamespace = serviceNamespace.Substring(0, -1);
if(localNamespace.EndsWith("."))
localNamespace = localNamespace.Substring(0, -1);
ServiceNamespace = serviceNamespace;
LocalNamespace = localNamespace;
}
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
assemblyName = null;
typeName = string.Format("{0}:#{1}", serializedType.Name, ServiceNamespace); // MS format
}
public override Type BindToType(string assemblyName, string typeName)
{
string jsonDotNetType = string.Format("{0}.{1}", LocalNamespace, typeName.Substring(0, typeName.IndexOf(":#")));
return Type.GetType(jsonDotNetType);
}
}
Có một tùy chọn khác cho phép tuần tự hóa tên thuộc tính loại tùy chỉnh trong Json.NET
. Ý tưởng không viết thuộc tính mặc định là $type
, nhưng giới thiệu tên loại là thuộc tính của lớp đó.
Giả sử chúng ta có một lớp Location
:
public class Location
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
tiên, chúng ta cần phải giới thiệu loại tên thuộc tính và sửa đổi các lớp như thể hiện dưới đây:
public class Location
{
[JsonProperty("__type")]
public string EntityTypeName
{
get
{
var typeName = string.Format("{0}, {1}", GetType().FullName, GetType().Namespace);
return typeName;
}
}
public double Latitude { get; set; }
public double Longitude { get; set; }
}
Sau đó, thiết lập JsonSerializerSettings.TypeNameHandling
-TypeNameHandling.None
để deserializer bỏ qua việc hiển thị thuộc tính mặc định $type
.
Vậy đó.
Ví dụ
var point = new Location() { Latitude = 51.5033630, Longitude = -0.1276250 };
var jsonLocation = JsonConvert.SerializeObject(point, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.None, //do not write type property(!)
});
Console.WriteLine(jsonLocation);
quả
{"__type":"Namespace.Location, Namespace","Latitude":51.503363,"Longitude":-0.127625}
Tôi không thấy cách deserializing sẽ xác định loại chính xác với giải pháp của bạn. Bạn có thể giải thích? –
Để deserialize, hãy thử 'JsonCreationConverter', ví dụ: xem http://stackoverflow.com/questions/8030538 – xmedeko
khi tuần tự, có một cách tốt đẹp để ghi đè lên các tên thuộc tính:
public class CustomJsonWriter : JsonTextWriter
{
public CustomJsonWriter(TextWriter writer) : base(writer)
{
}
public override void WritePropertyName(string name, bool escape)
{
if (name == "$type") name = "__type";
base.WritePropertyName(name, escape);
}
}
var serializer = new JsonSerializer();
var writer = new StreamWriter(stream) { AutoFlush = true };
serializer.Serialize(new CustomJsonWriter(writer), objectToSerialize);
tôi đã không cố gắng deserialization được nêu ra, nhưng trong trường hợp xấu nhất tôi có thể sử dụng:
json.Replace("\"__type": \"", "\"type\": \"$type\");
Tôi phải làm điều này cho API REST REST của tôi là Angular.js disregards tên trường bắt đầu bằng ký hiệu đô la ($).
Vì vậy, đây là giải pháp đổi tên $type
thành __type
cho toàn bộ API Web và hoạt động cả hai cho việc tuần tự hóa và cách ly hóa.
Để có thể sử dụng một tùy chỉnh JsonWriter
và một tùy chỉnh JsonReader
(như đề xuất trong câu trả lời khác cho câu hỏi này), chúng ta phải kế thừa JsonMediaTypeFormatter
và ghi đè lên các phương pháp tương ứng:
internal class CustomJsonNetFormatter : JsonMediaTypeFormatter
{
public override JsonReader CreateJsonReader(Type type, Stream readStream, Encoding effectiveEncoding)
{
return new CustomJsonReader(readStream, effectiveEncoding);
}
public override JsonWriter CreateJsonWriter(Type type, Stream writeStream, Encoding effectiveEncoding)
{
return new CustomJsonWriter(writeStream, effectiveEncoding);
}
private class CustomJsonWriter : JsonTextWriter
{
public CustomJsonWriter(Stream writeStream, Encoding effectiveEncoding)
: base(new StreamWriter(writeStream, effectiveEncoding))
{
}
public override void WritePropertyName(string name, bool escape)
{
if (name == "$type") name = "__type";
base.WritePropertyName(name, escape);
}
}
private class CustomJsonReader : JsonTextReader
{
public CustomJsonReader(Stream readStream, Encoding effectiveEncoding)
: base(new StreamReader(readStream, effectiveEncoding))
{
}
public override bool Read()
{
var hasToken = base.Read();
if (hasToken && TokenType == JsonToken.PropertyName && Value != null && Value.Equals("__type"))
{
SetToken(JsonToken.PropertyName, "$type");
}
return hasToken;
}
}
}
Trong số tất nhiên bạn cần đăng ký trình định dạng tùy chỉnh trong số WebApiConfig
của mình. Vì vậy, chúng tôi thay thế trình định dạng Json.NET mặc định bằng tùy chỉnh của chúng tôi:
config.Formatters.Remove(config.Formatters.JsonFormatter);
config.Formatters.Add(new CustomJsonNetFormatter());
Xong.
Bạn cũng có thể làm theo cách này:
[JsonConverter(typeof(JsonSubtypes), "ClassName")]
public class Annimal
{
public virtual string ClassName { get; }
public string Color { get; set; }
}
Bạn sẽ cần bộ chuyển đổi JsonSubtypes
đó không phải là một phần của dự án Newtonsoft.Json
.
- 1. Tính năng đổi tên Json.net
- 2. Làm cách nào để thay đổi tên thuộc tính khi tuần tự hóa với Json.net?
- 3. Thay đổi loại bảng thành InnoDB
- 4. ClearCase: thay đổi tên loại nhánh?
- 5. VB6 Editor thay đổi trường hợp tên biến!
- 6. JSON.NET - Loại điều kiện Deserialization
- 7. Không thể deserialize JSON mảng thành loại - Json.NET
- 8. Thay đổi đột phá CamelCase trong phiên bản Json.NET 4
- 9. Thay đổi loại cột từ ntext thành varbinary (max)
- 10. Thay đổi trường hợp chữ cái của các tên cột
- 11. Làm cách nào để ánh xạ các tên trường JSON thành các tên trường đối tượng khác nhau?
- 12. Xử lý các thay đổi không gian tên với TypeNameHandling.All
- 13. Thay đổi loại trường trong một Django ModelFormset
- 14. Kiểm tra xem chuỗi có thể được chuyển đổi thành loại khác không, loại khác nhau
- 15. Thay đổi tên trường trong quản trị django
- 16. Loại bỏ trường dữ liệu Java theo loại trường khác
- 17. Json.net lỏng lẻo so với deserialization loại
- 18. Chia sẻ lại các trường thay đổi thành chỉ đọc
- 19. Bỏ qua các trường rỗng trong Json.net
- 20. Làm cách nào để thay đổi loại đầu mũi tên?
- 21. Tôi muốn thay đổi phím 'return' của khóa ảo iphone thành tên khác
- 22. Các loại trường hợp khác nhau là gì?
- 23. NHibernate - Thay đổi loại phụ
- 24. Thay đổi loại cột có số từ varchar thành int
- 25. TYPO3: Thay đổi plugin từ USER thành USER_INT loại
- 26. JSON.net - trường là chuỗi hoặc Danh sách <string>
- 27. Tự động cập nhật trường khi một trường khác nhau được thay đổi
- 28. Các loại thay thế kiểu trường thực thể Symfony2 thành "thuộc tính" hoặc "__toString()"?
- 29. Đổi tên một môi trường bằng virtualenvwrapper
- 30. Đổi tên my.packages thành my.package
Tôi cũng cần điều này, ví dụ [JSON-LD] (http://json-ld.org) sử dụng '@ type' –