View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.layout;
18  
19  import java.nio.charset.Charset;
20  import java.util.HashMap;
21  import java.util.Map;
22  
23  import org.apache.logging.log4j.core.Layout;
24  import org.apache.logging.log4j.core.config.Node;
25  import org.apache.logging.log4j.core.config.plugins.Plugin;
26  import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
27  import org.apache.logging.log4j.core.config.plugins.PluginFactory;
28  import org.apache.logging.log4j.core.util.Constants;
29  
30  /**
31   * Appends a series of JSON events as strings serialized as bytes.
32   *
33   * <h3>Complete well-formed JSON vs. fragment JSON</h3>
34   * <p>
35   * If you configure {@code complete="true"}, the appender outputs a well-formed JSON document. By default, with {@code complete="false"},
36   * you should include the output as an <em>external file</em> in a separate file to form a well-formed JSON document.
37   * </p>
38   * <p>
39   * A well-formed JSON event follows this pattern:
40   * </p>
41   *
42   * <pre>
43   * {
44    "timeMillis": 1,
45    "thread": "MyThreadName",
46    "level": "DEBUG",
47    "loggerName": "a.B",
48    "marker": {
49      "name": "Marker1",
50      "parents": [{
51        "name": "ParentMarker1",
52        "parents": [{
53          "name": "GrandMotherMarker"
54        }, {
55          "name": "GrandFatherMarker"
56        }]
57      }, {
58        "name": "GrandFatherMarker"
59      }]
60    },
61    "message": "Msg",
62    "thrown": {
63      "cause": {
64        "commonElementCount": 27,
65        "extendedStackTrace": [{
66          "class": "org.apache.logging.log4j.core.layout.LogEventFixtures",
67          "method": "createLogEvent",
68          "file": "LogEventFixtures.java",
69          "line": 53,
70          "exact": false,
71          "location": "test-classes/",
72          "version": "?"
73        }],
74        "localizedMessage": "testNPEx",
75        "message": "testNPEx",
76        "name": "java.lang.NullPointerException"
77      },
78      "commonElementCount": 0,
79      "extendedStackTrace": [{
80        "class": "org.apache.logging.log4j.core.layout.LogEventFixtures",
81        "method": "createLogEvent",
82        "file": "LogEventFixtures.java",
83        "line": 56,
84        "exact": true,
85        "location": "test-classes/",
86        "version": "?"
87      }, {
88        "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
89        "method": "testAllFeatures",
90        "file": "JsonLayoutTest.java",
91        "line": 105,
92        "exact": true,
93        "location": "test-classes/",
94        "version": "?"
95      }, {
96        "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
97        "method": "testLocationOnCompactOnMdcOn",
98        "file": "JsonLayoutTest.java",
99        "line": 268,
100       "exact": true,
101       "location": "test-classes/",
102       "version": "?"
103     }, {
104       "class": "sun.reflect.NativeMethodAccessorImpl",
105       "method": "invoke",
106       "line": -1,
107       "exact": false,
108       "location": "?",
109       "version": "1.7.0_55"
110     }, {
111       "class": "sun.reflect.NativeMethodAccessorImpl",
112       "method": "invoke",
113       "line": -1,
114       "exact": false,
115       "location": "?",
116       "version": "1.7.0_55"
117     }, {
118       "class": "sun.reflect.DelegatingMethodAccessorImpl",
119       "method": "invoke",
120       "line": -1,
121       "exact": false,
122       "location": "?",
123       "version": "1.7.0_55"
124     }, {
125       "class": "java.lang.reflect.Method",
126       "method": "invoke",
127       "line": -1,
128       "exact": false,
129       "location": "?",
130       "version": "1.7.0_55"
131     }, {
132       "class": "org.junit.runners.model.FrameworkMethod$1",
133       "method": "runReflectiveCall",
134       "file": "FrameworkMethod.java",
135       "line": 47,
136       "exact": true,
137       "location": "junit-4.11.jar",
138       "version": "?"
139     }, {
140       "class": "org.junit.internal.runners.model.ReflectiveCallable",
141       "method": "run",
142       "file": "ReflectiveCallable.java",
143       "line": 12,
144       "exact": true,
145       "location": "junit-4.11.jar",
146       "version": "?"
147     }, {
148       "class": "org.junit.runners.model.FrameworkMethod",
149       "method": "invokeExplosively",
150       "file": "FrameworkMethod.java",
151       "line": 44,
152       "exact": true,
153       "location": "junit-4.11.jar",
154       "version": "?"
155     }, {
156       "class": "org.junit.internal.runners.statements.InvokeMethod",
157       "method": "evaluate",
158       "file": "InvokeMethod.java",
159       "line": 17,
160       "exact": true,
161       "location": "junit-4.11.jar",
162       "version": "?"
163     }, {
164       "class": "org.junit.runners.ParentRunner",
165       "method": "runLeaf",
166       "file": "ParentRunner.java",
167       "line": 271,
168       "exact": true,
169       "location": "junit-4.11.jar",
170       "version": "?"
171     }, {
172       "class": "org.junit.runners.BlockJUnit4ClassRunner",
173       "method": "runChild",
174       "file": "BlockJUnit4ClassRunner.java",
175       "line": 70,
176       "exact": true,
177       "location": "junit-4.11.jar",
178       "version": "?"
179     }, {
180       "class": "org.junit.runners.BlockJUnit4ClassRunner",
181       "method": "runChild",
182       "file": "BlockJUnit4ClassRunner.java",
183       "line": 50,
184       "exact": true,
185       "location": "junit-4.11.jar",
186       "version": "?"
187     }, {
188       "class": "org.junit.runners.ParentRunner$3",
189       "method": "run",
190       "file": "ParentRunner.java",
191       "line": 238,
192       "exact": true,
193       "location": "junit-4.11.jar",
194       "version": "?"
195     }, {
196       "class": "org.junit.runners.ParentRunner$1",
197       "method": "schedule",
198       "file": "ParentRunner.java",
199       "line": 63,
200       "exact": true,
201       "location": "junit-4.11.jar",
202       "version": "?"
203     }, {
204       "class": "org.junit.runners.ParentRunner",
205       "method": "runChildren",
206       "file": "ParentRunner.java",
207       "line": 236,
208       "exact": true,
209       "location": "junit-4.11.jar",
210       "version": "?"
211     }, {
212       "class": "org.junit.runners.ParentRunner",
213       "method": "access$000",
214       "file": "ParentRunner.java",
215       "line": 53,
216       "exact": true,
217       "location": "junit-4.11.jar",
218       "version": "?"
219     }, {
220       "class": "org.junit.runners.ParentRunner$2",
221       "method": "evaluate",
222       "file": "ParentRunner.java",
223       "line": 229,
224       "exact": true,
225       "location": "junit-4.11.jar",
226       "version": "?"
227     }, {
228       "class": "org.junit.internal.runners.statements.RunBefores",
229       "method": "evaluate",
230       "file": "RunBefores.java",
231       "line": 26,
232       "exact": true,
233       "location": "junit-4.11.jar",
234       "version": "?"
235     }, {
236       "class": "org.junit.internal.runners.statements.RunAfters",
237       "method": "evaluate",
238       "file": "RunAfters.java",
239       "line": 27,
240       "exact": true,
241       "location": "junit-4.11.jar",
242       "version": "?"
243     }, {
244       "class": "org.junit.runners.ParentRunner",
245       "method": "run",
246       "file": "ParentRunner.java",
247       "line": 309,
248       "exact": true,
249       "location": "junit-4.11.jar",
250       "version": "?"
251     }, {
252       "class": "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference",
253       "method": "run",
254       "file": "JUnit4TestReference.java",
255       "line": 50,
256       "exact": true,
257       "location": ".cp/",
258       "version": "?"
259     }, {
260       "class": "org.eclipse.jdt.internal.junit.runner.TestExecution",
261       "method": "run",
262       "file": "TestExecution.java",
263       "line": 38,
264       "exact": true,
265       "location": ".cp/",
266       "version": "?"
267     }, {
268       "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
269       "method": "runTests",
270       "file": "RemoteTestRunner.java",
271       "line": 467,
272       "exact": true,
273       "location": ".cp/",
274       "version": "?"
275     }, {
276       "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
277       "method": "runTests",
278       "file": "RemoteTestRunner.java",
279       "line": 683,
280       "exact": true,
281       "location": ".cp/",
282       "version": "?"
283     }, {
284       "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
285       "method": "run",
286       "file": "RemoteTestRunner.java",
287       "line": 390,
288       "exact": true,
289       "location": ".cp/",
290       "version": "?"
291     }, {
292       "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
293       "method": "main",
294       "file": "RemoteTestRunner.java",
295       "line": 197,
296       "exact": true,
297       "location": ".cp/",
298       "version": "?"
299     }],
300     "localizedMessage": "testIOEx",
301     "message": "testIOEx",
302     "name": "java.io.IOException",
303     "suppressed": [{
304       "commonElementCount": 0,
305       "extendedStackTrace": [{
306         "class": "org.apache.logging.log4j.core.layout.LogEventFixtures",
307         "method": "createLogEvent",
308         "file": "LogEventFixtures.java",
309         "line": 57,
310         "exact": true,
311         "location": "test-classes/",
312         "version": "?"
313       }, {
314         "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
315         "method": "testAllFeatures",
316         "file": "JsonLayoutTest.java",
317         "line": 105,
318         "exact": true,
319         "location": "test-classes/",
320         "version": "?"
321       }, {
322         "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
323         "method": "testLocationOnCompactOnMdcOn",
324         "file": "JsonLayoutTest.java",
325         "line": 268,
326         "exact": true,
327         "location": "test-classes/",
328         "version": "?"
329       }, {
330         "class": "sun.reflect.NativeMethodAccessorImpl",
331         "method": "invoke",
332         "line": -1,
333         "exact": false,
334         "location": "?",
335         "version": "1.7.0_55"
336       }, {
337         "class": "sun.reflect.NativeMethodAccessorImpl",
338         "method": "invoke",
339         "line": -1,
340         "exact": false,
341         "location": "?",
342         "version": "1.7.0_55"
343       }, {
344         "class": "sun.reflect.DelegatingMethodAccessorImpl",
345         "method": "invoke",
346         "line": -1,
347         "exact": false,
348         "location": "?",
349         "version": "1.7.0_55"
350       }, {
351         "class": "java.lang.reflect.Method",
352         "method": "invoke",
353         "line": -1,
354         "exact": false,
355         "location": "?",
356         "version": "1.7.0_55"
357       }, {
358         "class": "org.junit.runners.model.FrameworkMethod$1",
359         "method": "runReflectiveCall",
360         "file": "FrameworkMethod.java",
361         "line": 47,
362         "exact": true,
363         "location": "junit-4.11.jar",
364         "version": "?"
365       }, {
366         "class": "org.junit.internal.runners.model.ReflectiveCallable",
367         "method": "run",
368         "file": "ReflectiveCallable.java",
369         "line": 12,
370         "exact": true,
371         "location": "junit-4.11.jar",
372         "version": "?"
373       }, {
374         "class": "org.junit.runners.model.FrameworkMethod",
375         "method": "invokeExplosively",
376         "file": "FrameworkMethod.java",
377         "line": 44,
378         "exact": true,
379         "location": "junit-4.11.jar",
380         "version": "?"
381       }, {
382         "class": "org.junit.internal.runners.statements.InvokeMethod",
383         "method": "evaluate",
384         "file": "InvokeMethod.java",
385         "line": 17,
386         "exact": true,
387         "location": "junit-4.11.jar",
388         "version": "?"
389       }, {
390         "class": "org.junit.runners.ParentRunner",
391         "method": "runLeaf",
392         "file": "ParentRunner.java",
393         "line": 271,
394         "exact": true,
395         "location": "junit-4.11.jar",
396         "version": "?"
397       }, {
398         "class": "org.junit.runners.BlockJUnit4ClassRunner",
399         "method": "runChild",
400         "file": "BlockJUnit4ClassRunner.java",
401         "line": 70,
402         "exact": true,
403         "location": "junit-4.11.jar",
404         "version": "?"
405       }, {
406         "class": "org.junit.runners.BlockJUnit4ClassRunner",
407         "method": "runChild",
408         "file": "BlockJUnit4ClassRunner.java",
409         "line": 50,
410         "exact": true,
411         "location": "junit-4.11.jar",
412         "version": "?"
413       }, {
414         "class": "org.junit.runners.ParentRunner$3",
415         "method": "run",
416         "file": "ParentRunner.java",
417         "line": 238,
418         "exact": true,
419         "location": "junit-4.11.jar",
420         "version": "?"
421       }, {
422         "class": "org.junit.runners.ParentRunner$1",
423         "method": "schedule",
424         "file": "ParentRunner.java",
425         "line": 63,
426         "exact": true,
427         "location": "junit-4.11.jar",
428         "version": "?"
429       }, {
430         "class": "org.junit.runners.ParentRunner",
431         "method": "runChildren",
432         "file": "ParentRunner.java",
433         "line": 236,
434         "exact": true,
435         "location": "junit-4.11.jar",
436         "version": "?"
437       }, {
438         "class": "org.junit.runners.ParentRunner",
439         "method": "access$000",
440         "file": "ParentRunner.java",
441         "line": 53,
442         "exact": true,
443         "location": "junit-4.11.jar",
444         "version": "?"
445       }, {
446         "class": "org.junit.runners.ParentRunner$2",
447         "method": "evaluate",
448         "file": "ParentRunner.java",
449         "line": 229,
450         "exact": true,
451         "location": "junit-4.11.jar",
452         "version": "?"
453       }, {
454         "class": "org.junit.internal.runners.statements.RunBefores",
455         "method": "evaluate",
456         "file": "RunBefores.java",
457         "line": 26,
458         "exact": true,
459         "location": "junit-4.11.jar",
460         "version": "?"
461       }, {
462         "class": "org.junit.internal.runners.statements.RunAfters",
463         "method": "evaluate",
464         "file": "RunAfters.java",
465         "line": 27,
466         "exact": true,
467         "location": "junit-4.11.jar",
468         "version": "?"
469       }, {
470         "class": "org.junit.runners.ParentRunner",
471         "method": "run",
472         "file": "ParentRunner.java",
473         "line": 309,
474         "exact": true,
475         "location": "junit-4.11.jar",
476         "version": "?"
477       }, {
478         "class": "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference",
479         "method": "run",
480         "file": "JUnit4TestReference.java",
481         "line": 50,
482         "exact": true,
483         "location": ".cp/",
484         "version": "?"
485       }, {
486         "class": "org.eclipse.jdt.internal.junit.runner.TestExecution",
487         "method": "run",
488         "file": "TestExecution.java",
489         "line": 38,
490         "exact": true,
491         "location": ".cp/",
492         "version": "?"
493       }, {
494         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
495         "method": "runTests",
496         "file": "RemoteTestRunner.java",
497         "line": 467,
498         "exact": true,
499         "location": ".cp/",
500         "version": "?"
501       }, {
502         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
503         "method": "runTests",
504         "file": "RemoteTestRunner.java",
505         "line": 683,
506         "exact": true,
507         "location": ".cp/",
508         "version": "?"
509       }, {
510         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
511         "method": "run",
512         "file": "RemoteTestRunner.java",
513         "line": 390,
514         "exact": true,
515         "location": ".cp/",
516         "version": "?"
517       }, {
518         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
519         "method": "main",
520         "file": "RemoteTestRunner.java",
521         "line": 197,
522         "exact": true,
523         "location": ".cp/",
524         "version": "?"
525       }],
526       "localizedMessage": "I am suppressed exception 1",
527       "message": "I am suppressed exception 1",
528       "name": "java.lang.IndexOutOfBoundsException"
529     }, {
530       "commonElementCount": 0,
531       "extendedStackTrace": [{
532         "class": "org.apache.logging.log4j.core.layout.LogEventFixtures",
533         "method": "createLogEvent",
534         "file": "LogEventFixtures.java",
535         "line": 58,
536         "exact": true,
537         "location": "test-classes/",
538         "version": "?"
539       }, {
540         "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
541         "method": "testAllFeatures",
542         "file": "JsonLayoutTest.java",
543         "line": 105,
544         "exact": true,
545         "location": "test-classes/",
546         "version": "?"
547       }, {
548         "class": "org.apache.logging.log4j.core.layout.JsonLayoutTest",
549         "method": "testLocationOnCompactOnMdcOn",
550         "file": "JsonLayoutTest.java",
551         "line": 268,
552         "exact": true,
553         "location": "test-classes/",
554         "version": "?"
555       }, {
556         "class": "sun.reflect.NativeMethodAccessorImpl",
557         "method": "invoke",
558         "line": -1,
559         "exact": false,
560         "location": "?",
561         "version": "1.7.0_55"
562       }, {
563         "class": "sun.reflect.NativeMethodAccessorImpl",
564         "method": "invoke",
565         "line": -1,
566         "exact": false,
567         "location": "?",
568         "version": "1.7.0_55"
569       }, {
570         "class": "sun.reflect.DelegatingMethodAccessorImpl",
571         "method": "invoke",
572         "line": -1,
573         "exact": false,
574         "location": "?",
575         "version": "1.7.0_55"
576       }, {
577         "class": "java.lang.reflect.Method",
578         "method": "invoke",
579         "line": -1,
580         "exact": false,
581         "location": "?",
582         "version": "1.7.0_55"
583       }, {
584         "class": "org.junit.runners.model.FrameworkMethod$1",
585         "method": "runReflectiveCall",
586         "file": "FrameworkMethod.java",
587         "line": 47,
588         "exact": true,
589         "location": "junit-4.11.jar",
590         "version": "?"
591       }, {
592         "class": "org.junit.internal.runners.model.ReflectiveCallable",
593         "method": "run",
594         "file": "ReflectiveCallable.java",
595         "line": 12,
596         "exact": true,
597         "location": "junit-4.11.jar",
598         "version": "?"
599       }, {
600         "class": "org.junit.runners.model.FrameworkMethod",
601         "method": "invokeExplosively",
602         "file": "FrameworkMethod.java",
603         "line": 44,
604         "exact": true,
605         "location": "junit-4.11.jar",
606         "version": "?"
607       }, {
608         "class": "org.junit.internal.runners.statements.InvokeMethod",
609         "method": "evaluate",
610         "file": "InvokeMethod.java",
611         "line": 17,
612         "exact": true,
613         "location": "junit-4.11.jar",
614         "version": "?"
615       }, {
616         "class": "org.junit.runners.ParentRunner",
617         "method": "runLeaf",
618         "file": "ParentRunner.java",
619         "line": 271,
620         "exact": true,
621         "location": "junit-4.11.jar",
622         "version": "?"
623       }, {
624         "class": "org.junit.runners.BlockJUnit4ClassRunner",
625         "method": "runChild",
626         "file": "BlockJUnit4ClassRunner.java",
627         "line": 70,
628         "exact": true,
629         "location": "junit-4.11.jar",
630         "version": "?"
631       }, {
632         "class": "org.junit.runners.BlockJUnit4ClassRunner",
633         "method": "runChild",
634         "file": "BlockJUnit4ClassRunner.java",
635         "line": 50,
636         "exact": true,
637         "location": "junit-4.11.jar",
638         "version": "?"
639       }, {
640         "class": "org.junit.runners.ParentRunner$3",
641         "method": "run",
642         "file": "ParentRunner.java",
643         "line": 238,
644         "exact": true,
645         "location": "junit-4.11.jar",
646         "version": "?"
647       }, {
648         "class": "org.junit.runners.ParentRunner$1",
649         "method": "schedule",
650         "file": "ParentRunner.java",
651         "line": 63,
652         "exact": true,
653         "location": "junit-4.11.jar",
654         "version": "?"
655       }, {
656         "class": "org.junit.runners.ParentRunner",
657         "method": "runChildren",
658         "file": "ParentRunner.java",
659         "line": 236,
660         "exact": true,
661         "location": "junit-4.11.jar",
662         "version": "?"
663       }, {
664         "class": "org.junit.runners.ParentRunner",
665         "method": "access$000",
666         "file": "ParentRunner.java",
667         "line": 53,
668         "exact": true,
669         "location": "junit-4.11.jar",
670         "version": "?"
671       }, {
672         "class": "org.junit.runners.ParentRunner$2",
673         "method": "evaluate",
674         "file": "ParentRunner.java",
675         "line": 229,
676         "exact": true,
677         "location": "junit-4.11.jar",
678         "version": "?"
679       }, {
680         "class": "org.junit.internal.runners.statements.RunBefores",
681         "method": "evaluate",
682         "file": "RunBefores.java",
683         "line": 26,
684         "exact": true,
685         "location": "junit-4.11.jar",
686         "version": "?"
687       }, {
688         "class": "org.junit.internal.runners.statements.RunAfters",
689         "method": "evaluate",
690         "file": "RunAfters.java",
691         "line": 27,
692         "exact": true,
693         "location": "junit-4.11.jar",
694         "version": "?"
695       }, {
696         "class": "org.junit.runners.ParentRunner",
697         "method": "run",
698         "file": "ParentRunner.java",
699         "line": 309,
700         "exact": true,
701         "location": "junit-4.11.jar",
702         "version": "?"
703       }, {
704         "class": "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference",
705         "method": "run",
706         "file": "JUnit4TestReference.java",
707         "line": 50,
708         "exact": true,
709         "location": ".cp/",
710         "version": "?"
711       }, {
712         "class": "org.eclipse.jdt.internal.junit.runner.TestExecution",
713         "method": "run",
714         "file": "TestExecution.java",
715         "line": 38,
716         "exact": true,
717         "location": ".cp/",
718         "version": "?"
719       }, {
720         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
721         "method": "runTests",
722         "file": "RemoteTestRunner.java",
723         "line": 467,
724         "exact": true,
725         "location": ".cp/",
726         "version": "?"
727       }, {
728         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
729         "method": "runTests",
730         "file": "RemoteTestRunner.java",
731         "line": 683,
732         "exact": true,
733         "location": ".cp/",
734         "version": "?"
735       }, {
736         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
737         "method": "run",
738         "file": "RemoteTestRunner.java",
739         "line": 390,
740         "exact": true,
741         "location": ".cp/",
742         "version": "?"
743       }, {
744         "class": "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner",
745         "method": "main",
746         "file": "RemoteTestRunner.java",
747         "line": 197,
748         "exact": true,
749         "location": ".cp/",
750         "version": "?"
751       }],
752       "localizedMessage": "I am suppressed exception 2",
753       "message": "I am suppressed exception 2",
754       "name": "java.lang.IndexOutOfBoundsException"
755     }]
756   },
757   "loggerFQCN": "f.q.c.n",
758   "endOfBatch": false,
759   "contextMap": [{
760     "key": "MDC.B",
761     "value": "B_Value"
762   }, {
763     "key": "MDC.A",
764     "value": "A_Value"
765   }],
766   "contextStack": ["stack_msg1", "stack_msg2"],
767   "source": {
768     "class": "org.apache.logging.log4j.core.layout.LogEventFixtures",
769     "method": "createLogEvent",
770     "file": "LogEventFixtures.java",
771     "line": 54
772   }
773 }
774  * </pre>
775  * <p>
776  * If {@code complete="false"}, the appender does not write the JSON open array character "[" at the start of the document. and "]" and the
777  * end.
778  * </p>
779  * <p>
780  * This approach enforces the independence of the JsonLayout and the appender where you embed it.
781  * </p>
782  * <h3>Encoding</h3>
783  * <p>
784  * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise events containing non
785  * ASCII characters could result in corrupted log files.
786  * </p>
787  * <h3>Pretty vs. compact XML</h3>
788  * <p>
789  * By default, the JSON layout is not compact (a.k.a. not "pretty") with {@code compact="false"}, which means the appender uses end-of-line
790  * characters and indents lines to format the text. If {@code compact="true"}, then no end-of-line or indentation is used. Message content
791  * may contain, of course, escaped end-of-lines.
792  * </p>
793  */
794 @Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
795 public final class JsonLayout extends AbstractJacksonLayout {
796 
797     static final String CONTENT_TYPE = "application/json";
798 
799     private static final long serialVersionUID = 1L;
800 
801     protected JsonLayout(final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact,
802             boolean eventEol, final Charset charset) {
803         super(new JacksonFactory.JSON().newWriter(locationInfo, properties, compact), charset, compact, complete, eventEol);
804     }
805 
806     /**
807      * Returns appropriate JSON header.
808      *
809      * @return a byte array containing the header, opening the JSON array.
810      */
811     @Override
812     public byte[] getHeader() {
813         if (!this.complete) {
814             return null;
815         }
816         final StringBuilder buf = new StringBuilder();
817         buf.append('[');
818         buf.append(this.eol);
819         return getBytes(buf.toString());
820     }
821 
822     /**
823      * Returns appropriate JSON footer.
824      *
825      * @return a byte array containing the footer, closing the JSON array.
826      */
827     @Override
828     public byte[] getFooter() {
829         if (!this.complete) {
830             return null;
831         }
832         return getBytes(this.eol + ']' + this.eol);
833     }
834 
835     @Override
836     public Map<String, String> getContentFormat() {
837         final Map<String, String> result = new HashMap<String, String>();
838         result.put("version", "2.0");
839         return result;
840     }
841 
842     @Override
843     /**
844      * @return The content type.
845      */
846     public String getContentType() {
847         return CONTENT_TYPE + "; charset=" + this.getCharset();
848     }
849 
850     /**
851      * Creates a JSON Layout.
852      *
853      * @param locationInfo
854      *        If "true", includes the location information in the generated JSON.
855      * @param properties
856      *        If "true", includes the thread context in the generated JSON.
857      * @param complete
858      *        If "true", includes the JSON header and footer, defaults to "false".
859      * @param compact
860      *        If "true", does not use end-of-lines and indentation, defaults to "false".
861      * @param eventEol
862      *        If "true", forces an EOL after each log event (even if compact is "true"), defaults to "false". This
863      *        allows one even per line, even in compact mode.
864      * @param charset
865      *        The character set to use, if {@code null}, uses "UTF-8".
866      * @return A JSON Layout.
867      */
868     @PluginFactory
869     public static AbstractJacksonLayout createLayout(
870             // @formatter:off
871             @PluginAttribute(value = "locationInfo", defaultBoolean = false) final boolean locationInfo,
872             @PluginAttribute(value = "properties", defaultBoolean = false) final boolean properties,
873             @PluginAttribute(value = "complete", defaultBoolean = false) final boolean complete,
874             @PluginAttribute(value = "compact", defaultBoolean = false) final boolean compact,
875             @PluginAttribute(value = "eventEol", defaultBoolean = false) final boolean eventEol,
876             @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset
877             // @formatter:on
878     ) {
879         return new JsonLayout(locationInfo, properties, complete, compact, eventEol, charset);
880     }
881 
882     /**
883      * Creates a JSON Layout using the default settings.
884      *
885      * @return A JSON Layout.
886      */
887     public static AbstractJacksonLayout createDefaultLayout() {
888         return new JsonLayout(false, false, false, false, false, Constants.UTF_8);
889     }
890 }