/ src / Ryujinx.Common / Utilities / JsonHelper.cs
JsonHelper.cs
 1  using System.IO;
 2  using System.Text;
 3  using System.Text.Json;
 4  using System.Text.Json.Serialization.Metadata;
 5  
 6  namespace Ryujinx.Common.Utilities
 7  {
 8      public class JsonHelper
 9      {
10          private static readonly JsonNamingPolicy _snakeCasePolicy = new SnakeCaseNamingPolicy();
11          private const int DefaultFileWriteBufferSize = 4096;
12  
13          /// <summary>
14          /// Creates new serializer options with default settings.
15          /// </summary>
16          /// <remarks>
17          /// It is REQUIRED for you to save returned options statically or as a part of static serializer context
18          /// in order to avoid performance issues. You can safely modify returned options for your case before storing.
19          /// </remarks>
20          public static JsonSerializerOptions GetDefaultSerializerOptions(bool indented = true)
21          {
22              JsonSerializerOptions options = new()
23              {
24                  DictionaryKeyPolicy = _snakeCasePolicy,
25                  PropertyNamingPolicy = _snakeCasePolicy,
26                  WriteIndented = indented,
27                  AllowTrailingCommas = true,
28                  ReadCommentHandling = JsonCommentHandling.Skip,
29              };
30  
31              return options;
32          }
33  
34          public static string Serialize<T>(T value, JsonTypeInfo<T> typeInfo)
35          {
36              return JsonSerializer.Serialize(value, typeInfo);
37          }
38  
39          public static T Deserialize<T>(string value, JsonTypeInfo<T> typeInfo)
40          {
41              return JsonSerializer.Deserialize(value, typeInfo);
42          }
43  
44          public static void SerializeToFile<T>(string filePath, T value, JsonTypeInfo<T> typeInfo)
45          {
46              using FileStream file = File.Create(filePath, DefaultFileWriteBufferSize, FileOptions.WriteThrough);
47              JsonSerializer.Serialize(file, value, typeInfo);
48          }
49  
50          public static T DeserializeFromFile<T>(string filePath, JsonTypeInfo<T> typeInfo)
51          {
52              using FileStream file = File.OpenRead(filePath);
53              return JsonSerializer.Deserialize(file, typeInfo);
54          }
55  
56          public static void SerializeToStream<T>(Stream stream, T value, JsonTypeInfo<T> typeInfo)
57          {
58              JsonSerializer.Serialize(stream, value, typeInfo);
59          }
60  
61          private class SnakeCaseNamingPolicy : JsonNamingPolicy
62          {
63              public override string ConvertName(string name)
64              {
65                  if (string.IsNullOrEmpty(name))
66                  {
67                      return name;
68                  }
69  
70                  StringBuilder builder = new();
71  
72                  for (int i = 0; i < name.Length; i++)
73                  {
74                      char c = name[i];
75  
76                      if (char.IsUpper(c))
77                      {
78                          if (i == 0 || char.IsUpper(name[i - 1]))
79                          {
80                              builder.Append(char.ToLowerInvariant(c));
81                          }
82                          else
83                          {
84                              builder.Append('_');
85                              builder.Append(char.ToLowerInvariant(c));
86                          }
87                      }
88                      else
89                      {
90                          builder.Append(c);
91                      }
92                  }
93  
94                  return builder.ToString();
95              }
96          }
97      }
98  }