Copyright
이 모든 내용은 Pluralsight에 Xavier Morera가 올린 'Getting Started with JSON in C# Using Json.NET'라는 강의의 다섯번째 챕터를 듣고 정리한 것입니다(https://app.pluralsight.com/library/courses/json-csharp-jsondotnet-getting-started/table-of-contents).
Content
Outline
Manual Serialization/Deserialization
Fragments
Populate Objects
Merge Array Handling
Attributes
Memory Usage
Serializing and deserializing manually
Json.NET is extremely fast but it relies on reflection so if speed is key, serialize/deserialize manually using JsonTextReader/Writer. (Avoids using Reflection, Less memory usage, Fastest way of reading and writing JSON)
Writing
var builder = new StringBuilder(); //Never to use strings(immutable) if you're going to be changing them too much
StringWriter writer = new StringWriter(builder);
using (var jsonWriter = new JsonWriter(writer))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.WriteStartArray();
for (int i =0; i < numberOfView; i++)
{
jsonWriter.WriteStartObject();
....
jsonWriter.WriteEndObject();
}
jsonWriter.WriteEndArray();
}
Reading
var reader = new JsonTextReader(new StringReader()jsonStrings);
while(reader.Read())
{
if(reader.Value != null)
{
if(reader.TokenType == JsonToken.String....)
}
}
JSON Fragments (Deserialize only what you need!)
Large JSON documents or objects may take a lot of time serializing and deserializing. However, in certain scenarios you may have a very big JSON object, but you're only interested in a specific subsection of your data. With Json.NET it is possible to extract and work with a fragment of a JSON object using Linq.
Json.NET has the capability of extracting a subsection of a big JSON text, allowing you to deserialize only that small section. This is very beneficial both in terms of performance and simplicity because you're not deserializing the entire object, that's the first one, and second, it makes the code much more readable.
List<UserInteraction> userLogs = GetTestData(); //Generate huge data
string bigLog = JsonConvert.SerializeObject(userLogs);
JArray logs = JArray.Parse(bigLog); //bigLog is huge json string
List<CourseView> courses = new List<CourseView>(); //CourseView is an objects which we are interest in bigLog
foreach (JObject logEntry in logs)
{
courses.Add(logEntry["courseView"].ToObject<CourseView>()); //Using Linq to json to extract CourseView
}
Remember that readable and simple code is much better than code that's complex and difficult to read. By using JSON fragments it makes your code much more readable and easier to maintain.
PopulateObject
With JSON fragments you're able to extract and work with sections of a large JSON object. PopulateObject is the opposite functionality where you're able to write specific values to a large JSON object.
List<UserInteraction> userLogs = GetTestData(); //Generate huge data
string jsonReviewed = "{'reviewed' : true. 'processedBy' : [''ReviewerProcess'], 'reviewedDate : '" + DateTime.Now.ToUniversalTime().ToString("yyyy-mm-ddTHH:mm:ssK") + @"' }";
foreach(UserInteraction log in userLogs)
{
JsonConvert.PopulateObject(jsonReviewed, log);
}
JSON Merge (Merge JSON Objects) (Skip)
There are cases where you have two JSON objects that you need to merge. For example, we might have a large JSON array where each item might need to read an object from a different data source. This can be a complex operation or not. Json.NET provides the merge functionality from one object to another. Logic is very simple. Name value pairs are copied across, skipping nulls if the existing property is not null and you can even specify how to handle arrays via merge array handling. You have four options for arrays, concat, union, replace, and merge.
Attributes for performance (Serialize and Deserialize Only What You Need) (Skip)
JsonIgnore Attributes on class
Optimizing Memory Usage (Avoid Large Object Heap, Use Streams)
Memory usage is critical to performance, but more than that, it can lead to exceptions. Any object over 85 kilobytes in size goes directly to a large object heap and this can mean a few out of memory exception. This number(85) is a threshold that was obtained after multiple tests by Microsoft. The problem with the large object heap as opposed to heap generations 0, 1, and 2, is that it's not compacted and even though there are some improvements in .NET Framework 4.5 and up, the promise that your memory usage may grow and grow until your application can be in trouble. Json.NET helps you improve memory usage by using streams instead of loading entire strings into memory. It achieves this by reading from a client in a synchronous way, reading one piece at a time a large JSON.
using (StreamReader streamReader = new StreamReader(stream))
{
using (JsonReader jsonReader = new JsonTextReader(streamReader))
{
var jsonSerializer = new JsonSerializer();
List<UserInteraction> logsStream = jsonSerializer.Deserialize<List<UserInteraction>>(jsonReader);
//The key here is that we're loading the text in an asynchronous way
}
}
출처
이 모든 내용은 Pluralsight에 Xavier Morera가 올린 'Getting Started with JSON in C# Using Json.NET'라는 강의의 다섯번째 챕터를 듣고 정리한 것입니다(https://app.pluralsight.com/library/courses/json-csharp-jsondotnet-getting-started/table-of-contents). 제가 정리한 것보다 더 많은 내용과 Demo를 포함하고 있으며 최종 Summary는 생략하겠습니다. Microsoft 지원을 통해 한달간 무료로 Pluralsight의 강의를 들으실 수도 있습니다.
'Programming > etc' 카테고리의 다른 글
(Json.NET) Custom Serialization (0) | 2018.03.30 |
---|---|
(Json.NET) Settings & Attributes (0) | 2018.03.30 |
(Json.NET) Serialization Fundamentals (0) | 2018.03.30 |
Copyright
이 모든 내용은 Pluralsight에 Xavier Morera가 올린 'Getting Started with JSON in C# Using Json.NET'라는 강의의 네번째 챕터를 듣고 정리한 것입니다(https://app.pluralsight.com/library/courses/json-csharp-jsondotnet-getting-started/table-of-contents).
Content
Outline
Conditional Serialization
Custom JsonConverter
Callbacks
ITraceWriter for logging and debugging
Conditional Serialization
Conditional serialization may not be the case that you want to serialize an object as is, but instead only serialize based on specific conditions and this is what conditional serialization is for.
You can specify conditions in your code using ShouldSerialize which works by creating a function with a bool return type that has the name ShouldSerialize and the property name.
public class AuthorSS
{
public string Name { get; set; }
public bool IsActive { get; set; }
public string[] Courses { get; set; }
public bool ShouldSerializeCourses()
{
//If Author IsActive then Courses will be serialized
return IsActive;
}
}
target class(AuthorSS) to serialize has to have boolean member(IsActive) with bool ShouldSerialize"TargetMemberName"() method
Before Serializing the class, If IsActive set to true. then target member will be serialized. if not target member is not serialized.
Or you can use IContractResolver
The IContractResolver is very useful when you use classes that you have not defined or you do not want to add the ShouldSerialize methods to those classes, or if it's a third party code you can't modify the code or you decide you prefer to avoid placing attributes.
public class SelectiveContractResolver : DefaultContractResolver
{
private IList<string> propertiesList = null;
public SelectiveContractResolver(IList<string> propertiesToSerialize)
{
propertiesList = propertiesToSerialize; //Get strings of property names which want to serialize
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
return properties.Where(p => propertiesList.Contains(p.PropertyName)).ToList();
}
}
...
var contractResolver = new SelectiveContractResolver(propertiesToSerialize); //propertiesToSerialize is list of property name
string jsonstring = JsonConvert.SerializeObject(author, new JsonSerializerSettings
{
Formatting = Formatting.Indented,
ContractResolver = contractResolver
});
Custom JsonConverter
Json.NET provides JsonConvert as an easy to use wrapper over the JsonSerializer class to allow quick and easy conversion between .NET and JSON text. however, it may be possible that you want to extend or customize the serialization and deserialization process with a custom JSON converter based on the JsonConvert to fit exactly to your needs by overriding methods as required.
The JsonConverter class is the class responsible of converting from an object to JSON text and vice versa. It is extremely useful and easy to use, but what happens if you want to have finer control over the serialization and deserialization process? Well, you can create your own CustomJsonConverter class.
1. Create your own converter
2. Derived from JsonConvert
3. Override methods as needed
4. Set JsonSerializerSettings.Converters as a List<JsonConverter> with own custom converter
Callbacks
Serialization callbacks are methods that are raised before and after the serialization and deserialization process. They let you manipulate the objects or perform any operation before and after. A good example for using serialization callbacks is if you want it to have a functionality that logs the serialization time. The methods are OnSerializing and OnDeserializing, which are called before the conversion takes placed and OnSerialized and OnDeserialized which are called when the process completes.
public class Author
{
private Stopwatch timer = new Stopwatch();
public int age;
public string name { get; set; }
...
[OnSerializing]
internal void OnSerializingMethod(StreamingContext context)
{
timer.Reset(); timer.Start();
}
[OnSerialized]
internal void OnSerializedMethod(StreamingContext context)
{
timer.Stop();
}
[OnDeserializing]
internal void OnDeserializingMethod(StreamingContext context)
{
timer.Reset(); timer.Start();
}
[OnDeserialized]
internal void OnDeserializedMethod(StreamingContext context)
{
timer.Stop();
}
}
Logging and Debugging with ITraceWriter (Skip)
Debugging the serializer is not a common scenario, as in most cases everything just works, but what if you wanted to debug or if you want to understand exactly the serialization process, or you're running into an error and can't figure out what is the cause? Then you need the ITraceWriter. ITraceWriter is the method used for debugging the serialization process. Json.NET comes with a MemoryTraceWriter which logs all debugging information in memory. It's quick and easy to use or you can create your own custom TraceWriter.
출처
이 모든 내용은 Pluralsight에 Xavier Morera가 올린 'Getting Started with JSON in C# Using Json.NET'라는 강의의 네번째 챕터를 듣고 정리한 것입니다(https://app.pluralsight.com/library/courses/json-csharp-jsondotnet-getting-started/table-of-contents). 제가 정리한 것보다 더 많은 내용과 Demo를 포함하고 있으며 최종 Summary는 생략하겠습니다. Microsoft 지원을 통해 한달간 무료로 Pluralsight의 강의를 들으실 수도 있습니다.
'Programming > etc' 카테고리의 다른 글
(Json.NET) Performance Tips (0) | 2018.03.30 |
---|---|
(Json.NET) Settings & Attributes (0) | 2018.03.30 |
(Json.NET) Serialization Fundamentals (0) | 2018.03.30 |
Copyright
이 모든 내용은 Pluralsight에 Xavier Morera가 올린 'Getting Started with JSON in C# Using Json.NET'라는 강의의 세번째 챕터를 듣고 정리한 것입니다(https://app.pluralsight.com/library/courses/json-csharp-jsondotnet-getting-started/table-of-contents).
Content
Outline
Settings and Attributes
Settings
Attributes
Settings and Attributes
A setting is a user preference that is supplied during the conversion process. It can be specified as a property on the JsonSerializer class or using the JsonSerializer settings on JsonConvert.
An attribute is a declarative tag that is supplied on classes, properties, and more, that is taking into account during the serialization and deserialization process.
Settings
DateFormatHandling
With DateFormatHandling you tell Json.NET how to handle dates. e.g., the ISO date format or the Microsoft date format.
MissingMemberHandling
With MissingMemberHandling you tell Json.NET what to do when the JSON contains a member that is not defined. You can ignore or you can raise an error.
ReferenceLoopHandling
With ReferenceLoopHandling you tell Json.NET what to do when there is an object that references itself. You can ignore, raise an error, or serialize.
NullValueHandling
With NullValueHandling you tell Json.NET what to do when it runs into null values, both on serialization and deserialization.
DefaultValueHandling
With DefaultValueHandling you specify how to use the default values that are set using the DefaultValue attribute. [DefaultValue(3)] int defaultAgeIsThree;
Can ignore property which was set to default value when Serializing
Can populate default value to a property when Deserializing
ObjectCreationHandling
With ObjectCreationHandling you tell Json.NET how to handle objects that are created during the deserialization. By default, Json.NET sets values and appends values to existing collections. This might be the desired behavior in some cases, but in others it might not. You can specify if you want to reuse or replace the objects or collections that are set. This is particularly useful when you have constructors that populate values before the deserialization process.
TypeNameHandling
TypeNameHandling is very important because it tells Json.NET to preserve type information that's very useful when you're serializing and deserializing.
TypeNameAssemblyFormat
With TypeNameAssembly you tell Json.NET how you want type names written during the serialization process.
Binder
With Binder you tell Json.NET how to resolve type names to .NET types.
MetadataPropertyHandling
ConstructorHandling
ConstructorHandling is a way of telling Json.NET to specify which constructor to use, even if it's not a public constructor.
Converters
Converters is a way of telling Json.NET which converters you want to use during the deserialization and serialization process.
ContractResolver
With ContractResolver you specify to Json.NET how you want to control the serialization and deserialization without having attributes in your classes.
TraceWriter
TraceWriter is used for logging and debugging, and with Error you specify to Json.NET how is it that you want to handle errors.
Error
With Error you specify to Json.NET how is it that you want to handle errors.
Attributes
Attributes are declarative tags that are placed on classes, properties, and more and they provide additional information to Json.NET on how to do the serialization and deserialization process.
in Json.NET
JsonObjectAttribute
The JsonObjectAttribute is placed on classes to tell Json.NET how to serialize as a JsonObject.
JsonArrayAttribute
The JsonArrayAttribute is placed in collections and it tells Json.NET to serialize as a JsonArray.
JsonDictionaryAttribute
The JsonDictionaryAttribute is placed in dictionaries and it tells Json.NET how they should be serialized as JSON objects.
JsonPropertyAttribute
The JsonPropertyAttribute is used in fields and properties to control how they're serialized as properties in JsonObjects.
+ [JsonProperty(PropertyName = "AuthorName", Required = Required.Always, Order = 2)]
public string name { get; set; }
If Json.NET try to serialize the class without value of above property(name) throws an error - Useful when a specific member to be set before serialize.
And Serialized PropertyName set to "AuthorName". Setting PropertyName can be implicit like below "WhereInTheWorld"
+ [JsonProperty("WhereInTheWorld", DefaultValueHandling = DefaultValueHandling.Ignore)]
[DefaultValue("Costa Rica")]
public string location { get; set; }
if location property is set to "Costa Rica" just as same as DefaultValue above, then DefaultValueHandling.Ignore Attribute makes Json.NET not to serialize location property at all. It's useful to save some bytes.
JsonIgnoreAttribute
JsonIgnore tells Json.NET to ignore and do not include a property during serialization.
MemberSerialization OptIn, OptOut, Fields
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] //Only JsonProperty attached member is serialized
[JsonObject(MemberSerialization = MemberSerialization.OptOut)] //Just looking for which ones to ignore
[JsonObject(MemberSerialization = MemberSerialization.Field)] //Add some string on autogenerated field
public class AuthorJsonObjectOptIn
{
private string privateField;
[JsonProperty] private string privateFieldWithAttribute; //private field also serialized
[JsonProperty] public string name { get; set; } //Only this two member get serialize
public string[] courses { get; set; }
public DateTime since;
[NonSerialized] public bool happy; //Ignore this two member and serialize else including private member
[JsonIgnoreAttribute] public object issues { get; set; }
}
JsonConverterAttribute
The JsonConverter can be placed on classes, fields, or properties and it tells Json.NET to use a specific JsonConverter during the serialization process.
e.g. [JsonConverter(typeof(StringEnumConverter))] public Relationship relationship { get; set; } //Relationship is of type enum
if no Converter here, Json.NET serialize relationship(of type enum) as string like 1 or 2...
But with this converter it uses text in enum
JsonExtensionDataAttribute
The JsonExtensionDataAttribute is placed on a collection field or property and it tells Json.NET to use this as a catchall bucket to include any properties that do not have any matching class members.
JsonConstructorAttribute
The JsonConstructor attribute is placed on a constructor and it tells Json.NET to use this constructor during deserialization.
in Standard .NET Attributes
SerializableAttribute
The SerializableAttribute is used to indicate that a class can be serialized.
DataContractAttribute
The DataContractAttribute is used to specify that the type or class implements a data contract and is serializable.
DataMemberAttribute
The DataMemberAttribute which when applied to a member of a type specifies that the member is part of a data contract.
NonSerializedAttribute
NonSerializedAttribute which tells Json.NET that a particular field should not be serialized.
출처
이 모든 내용은 Pluralsight에 Xavier Morera가 올린 'Getting Started with JSON in C# Using Json.NET'라는 강의의 세번째 챕터를 듣고 정리한 것입니다(https://app.pluralsight.com/library/courses/json-csharp-jsondotnet-getting-started/table-of-contents). 제가 정리한 것보다 더 많은 내용과 Demo를 포함하고 있으며 최종 Summary는 생략하겠습니다. Microsoft 지원을 통해 한달간 무료로 Pluralsight의 강의를 들으실 수도 있습니다.
'Programming > etc' 카테고리의 다른 글
(Json.NET) Performance Tips (0) | 2018.03.30 |
---|---|
(Json.NET) Custom Serialization (0) | 2018.03.30 |
(Json.NET) Serialization Fundamentals (0) | 2018.03.30 |