4
4
using System . Text . Encodings . Web ;
5
5
using System . Text . Json ;
6
6
using System . Text . Json . Serialization ;
7
+ using JsonApiDotNetCore . Configuration ;
8
+ using JsonApiDotNetCore . Resources ;
9
+ using JsonApiDotNetCore . Resources . Annotations ;
7
10
using Microsoft . Extensions . Logging ;
8
11
9
12
namespace JsonApiDotNetCore . Middleware ;
@@ -14,8 +17,69 @@ internal abstract class TraceLogWriter
14
17
{
15
18
WriteIndented = true ,
16
19
Encoder = JavaScriptEncoder . UnsafeRelaxedJsonEscaping ,
17
- ReferenceHandler = ReferenceHandler . Preserve
20
+ ReferenceHandler = ReferenceHandler . IgnoreCycles ,
21
+ DefaultIgnoreCondition = JsonIgnoreCondition . WhenWritingNull ,
22
+ Converters =
23
+ {
24
+ new JsonStringEnumConverter ( ) ,
25
+ new ResourceTypeInTraceJsonConverter ( ) ,
26
+ new ResourceFieldInTraceJsonConverterFactory ( ) ,
27
+ new IdentifiableInTraceJsonConverter ( )
28
+ }
18
29
} ;
30
+
31
+ private sealed class ResourceTypeInTraceJsonConverter : JsonConverter < ResourceType >
32
+ {
33
+ public override ResourceType Read ( ref Utf8JsonReader reader , Type typeToConvert , JsonSerializerOptions options )
34
+ {
35
+ throw new NotSupportedException ( ) ;
36
+ }
37
+
38
+ public override void Write ( Utf8JsonWriter writer , ResourceType value , JsonSerializerOptions options )
39
+ {
40
+ writer . WriteStringValue ( value . PublicName ) ;
41
+ }
42
+ }
43
+
44
+ private sealed class ResourceFieldInTraceJsonConverterFactory : JsonConverterFactory
45
+ {
46
+ public override bool CanConvert ( Type typeToConvert )
47
+ {
48
+ return typeToConvert . IsAssignableTo ( typeof ( ResourceFieldAttribute ) ) ;
49
+ }
50
+
51
+ public override JsonConverter CreateConverter ( Type typeToConvert , JsonSerializerOptions options )
52
+ {
53
+ return new ResourceFieldInTraceJsonConverter ( ) ;
54
+ }
55
+
56
+ private sealed class ResourceFieldInTraceJsonConverter : JsonConverter < ResourceFieldAttribute >
57
+ {
58
+ public override ResourceFieldAttribute Read ( ref Utf8JsonReader reader , Type typeToConvert , JsonSerializerOptions options )
59
+ {
60
+ throw new NotSupportedException ( ) ;
61
+ }
62
+
63
+ public override void Write ( Utf8JsonWriter writer , ResourceFieldAttribute value , JsonSerializerOptions options )
64
+ {
65
+ writer . WriteStringValue ( value . PublicName ) ;
66
+ }
67
+ }
68
+ }
69
+
70
+ private sealed class IdentifiableInTraceJsonConverter : JsonConverter < IIdentifiable >
71
+ {
72
+ public override IIdentifiable Read ( ref Utf8JsonReader reader , Type typeToConvert , JsonSerializerOptions options )
73
+ {
74
+ throw new NotSupportedException ( ) ;
75
+ }
76
+
77
+ public override void Write ( Utf8JsonWriter writer , IIdentifiable value , JsonSerializerOptions options )
78
+ {
79
+ Type runtimeType = value . GetType ( ) ;
80
+ JsonSerializer . Serialize ( writer , value , runtimeType , options ) ;
81
+ }
82
+ }
19
83
}
20
84
21
85
internal sealed class TraceLogWriter < T > : TraceLogWriter
@@ -88,26 +152,12 @@ private static void WriteProperty(StringBuilder builder, PropertyInfo property,
88
152
builder . Append ( ": " ) ;
89
153
90
154
object ? value = property . GetValue ( instance ) ;
91
-
92
- if ( value == null )
93
- {
94
- builder . Append ( "null" ) ;
95
- }
96
- else if ( value is string stringValue )
97
- {
98
- builder . Append ( '"' ) ;
99
- builder . Append ( stringValue ) ;
100
- builder . Append ( '"' ) ;
101
- }
102
- else
103
- {
104
- WriteObject ( builder , value ) ;
105
- }
155
+ WriteObject ( builder , value ) ;
106
156
}
107
157
108
- private static void WriteObject ( StringBuilder builder , object value )
158
+ private static void WriteObject ( StringBuilder builder , object ? value )
109
159
{
110
- if ( HasToStringOverload ( value . GetType ( ) ) )
160
+ if ( value != null && value is not string && HasToStringOverload ( value . GetType ( ) ) )
111
161
{
112
162
builder . Append ( value ) ;
113
163
}
@@ -118,28 +168,19 @@ private static void WriteObject(StringBuilder builder, object value)
118
168
}
119
169
}
120
170
121
- private static bool HasToStringOverload ( Type ? type )
171
+ private static bool HasToStringOverload ( Type type )
122
172
{
123
- if ( type != null )
124
- {
125
- MethodInfo ? toStringMethod = type . GetMethod ( "ToString" , Array . Empty < Type > ( ) ) ;
126
-
127
- if ( toStringMethod != null && toStringMethod . DeclaringType != typeof ( object ) )
128
- {
129
- return true ;
130
- }
131
- }
132
-
133
- return false ;
173
+ MethodInfo ? toStringMethod = type . GetMethod ( "ToString" , Array . Empty < Type > ( ) ) ;
174
+ return toStringMethod != null && toStringMethod . DeclaringType != typeof ( object ) ;
134
175
}
135
176
136
- private static string SerializeObject ( object value )
177
+ private static string SerializeObject ( object ? value )
137
178
{
138
179
try
139
180
{
140
181
return JsonSerializer . Serialize ( value , SerializerOptions ) ;
141
182
}
142
- catch ( JsonException )
183
+ catch ( Exception exception ) when ( exception is JsonException or NotSupportedException )
143
184
{
144
185
// Never crash as a result of logging, this is best-effort only.
145
186
return "object" ;
0 commit comments