.katex { display: block; text-align: center; white-space: nowrap; }
.katex-display > .katex > .katex-html { display: block; }
.katex-display > .katex > .katex-html > .tag { position: absolute; right: 0px; }
.katex { font: 1.21em / 1.2 KaTeX_Main, "Times New Roman", serif; text-indent: 0px; text-rendering: auto; }
.katex * { }
.katex .katex-mathml { position: absolute; clip: rect(1px, 1px, 1px, 1px); padding: 0px; border: 0px; height: 1px; width: 1px; overflow: hidden; }
.katex .katex-html { }
.katex .katex-html > .newline { display: block; }
.katex .base { position: relative; display: inline-block; white-space: nowrap; width: min-content; }
.katex .strut { display: inline-block; }
.katex .textbf { font-weight: bold; }
.katex .textit { font-style: italic; }
.katex .textrm { font-family: KaTeX_Main; }
.katex .textsf { font-family: KaTeX_SansSerif; }
.katex .texttt { font-family: KaTeX_Typewriter; }
.katex .mathit { font-family: KaTeX_Math; font-style: italic; }
.katex .mathrm { font-style: normal; }
.katex .mathbf { font-family: KaTeX_Main; font-weight: bold; }
.katex .boldsymbol { font-family: KaTeX_Math; font-weight: bold; font-style: italic; }
.katex .amsrm { font-family: KaTeX_AMS; }
.katex .mathbb, .katex .textbb { font-family: KaTeX_AMS; }
.katex .mathcal { font-family: KaTeX_Caligraphic; }
.katex .mathfrak, .katex .textfrak { font-family: KaTeX_Fraktur; }
.katex .mathtt { font-family: KaTeX_Typewriter; }
.katex .mathscr, .katex .textscr { font-family: KaTeX_Script; }
.katex .mathsf, .katex .textsf { font-family: KaTeX_SansSerif; }
.katex .mainit { font-family: KaTeX_Main; font-style: italic; }
.katex .mainrm { font-family: KaTeX_Main; font-style: normal; }
.katex .vlist-t { display: inline-table; table-layout: fixed; }
.katex .vlist-r { display: table-row; }
.katex .vlist { display: table-cell; vertical-align: bottom; position: relative; }
.katex .vlist > span { display: block; height: 0px; position: relative; }
.katex .vlist > span > span { display: inline-block; }
.katex .vlist > span > .pstrut { overflow: hidden; width: 0px; }
.katex .vlist-t2 { margin-right: -2px; }
.katex .vlist-s { display: table-cell; vertical-align: bottom; font-size: 1px; width: 2px; min-width: 2px; }
.katex .msupsub { text-align: left; }
.katex .mfrac > span > span { text-align: center; }
.katex .mfrac .frac-line { display: inline-block; width: 100%; border-bottom-style: solid; }
.katex .mspace { display: inline-block; }
.katex .llap, .katex .rlap, .katex .clap { width: 0px; position: relative; }
.katex .llap > .inner, .katex .rlap > .inner, .katex .clap > .inner { position: absolute; }
.katex .llap > .fix, .katex .rlap > .fix, .katex .clap > .fix { display: inline-block; }
.katex .llap > .inner { right: 0px; }
.katex .rlap > .inner, .katex .clap > .inner { left: 0px; }
.katex .clap > .inner > span { margin-left: -50%; margin-right: 50%; }
.katex .rule { display: inline-block; border: 0px solid; position: relative; }
.katex .overline .overline-line, .katex .underline .underline-line, .katex .hline { display: inline-block; width: 100%; border-bottom-style: solid; }
.katex .hdashline { display: inline-block; width: 100%; border-bottom-style: dashed; }
.katex .sqrt > .root { margin-left: 0.277778em; margin-right: -0.555556em; }
.katex .sizing, .katex .fontsize-ensurer { display: inline-block; }
.katex .sizing.reset-size1.size1, .katex .fontsize-ensurer.reset-size1.size1 { font-size: 1em; }
.katex .sizing.reset-size1.size2, .katex .fontsize-ensurer.reset-size1.size2 { font-size: 1.2em; }
.katex .sizing.reset-size1.size3, .katex .fontsize-ensurer.reset-size1.size3 { font-size: 1.4em; }
.katex .sizing.reset-size1.size4, .katex .fontsize-ensurer.reset-size1.size4 { font-size: 1.6em; }
.katex .sizing.reset-size1.size5, .katex .fontsize-ensurer.reset-size1.size5 { font-size: 1.8em; }
.katex .sizing.reset-size1.size6, .katex .fontsize-ensurer.reset-size1.size6 { font-size: 2em; }
.katex .sizing.reset-size1.size7, .katex .fontsize-ensurer.reset-size1.size7 { font-size: 2.4em; }
.katex .sizing.reset-size1.size8, .katex .fontsize-ensurer.reset-size1.size8 { font-size: 2.88em; }
.katex .sizing.reset-size1.size9, .katex .fontsize-ensurer.reset-size1.size9 { font-size: 3.456em; }
.katex .sizing.reset-size1.size10, .katex .fontsize-ensurer.reset-size1.size10 { font-size: 4.148em; }
.katex .sizing.reset-size1.size11, .katex .fontsize-ensurer.reset-size1.size11 { font-size: 4.976em; }
.katex .sizing.reset-size2.size1, .katex .fontsize-ensurer.reset-size2.size1 { font-size: 0.833333em; }
.katex .sizing.reset-size2.size2, .katex .fontsize-ensurer.reset-size2.size2 { font-size: 1em; }
.katex .sizing.reset-size2.size3, .katex .fontsize-ensurer.reset-size2.size3 { font-size: 1.16667em; }
.katex .sizing.reset-size2.size4, .katex .fontsize-ensurer.reset-size2.size4 { font-size: 1.33333em; }
.katex .sizing.reset-size2.size5, .katex .fontsize-ensurer.reset-size2.size5 { font-size: 1.5em; }
.katex .sizing.reset-size2.size6, .katex .fontsize-ensurer.reset-size2.size6 { font-size: 1.66667em; }
.katex .sizing.reset-size2.size7, .katex .fontsize-ensurer.reset-size2.size7 { font-size: 2em; }
.katex .sizing.reset-size2.size8, .katex .fontsize-ensurer.reset-size2.size8 { font-size: 2.4em; }
.katex .sizing.reset-size2.size9, .katex .fontsize-ensurer.reset-size2.size9 { font-size: 2.88em; }
.katex .sizing.reset-size2.size10, .katex .fontsize-ensurer.reset-size2.size10 { font-size: 3.45667em; }
.katex .sizing.reset-size2.size11, .katex .fontsize-ensurer.reset-size2.size11 { font-size: 4.14667em; }
.katex .sizing.reset-size3.size1, .katex .fontsize-ensurer.reset-size3.size1 { font-size: 0.714286em; }
.katex .sizing.reset-size3.size2, .katex .fontsize-ensurer.reset-size3.size2 { font-size: 0.857143em; }
.katex .sizing.reset-size3.size3, .katex .fontsize-ensurer.reset-size3.size3 { font-size: 1em; }
.katex .sizing.reset-size3.size4, .katex .fontsize-ensurer.reset-size3.size4 { font-size: 1.14286em; }
.katex .sizing.reset-size3.size5, .katex .fontsize-ensurer.reset-size3.size5 { font-size: 1.28571em; }
.katex .sizing.reset-size3.size6, .katex .fontsize-ensurer.reset-size3.size6 { font-size: 1.42857em; }
.katex .sizing.reset-size3.size7, .katex .fontsize-ensurer.reset-size3.size7 { font-size: 1.71429em; }
.katex .sizing.reset-size3.size8, .katex .fontsize-ensurer.reset-size3.size8 { font-size: 2.05714em; }
.katex .sizing.reset-size3.size9, .katex .fontsize-ensurer.reset-size3.size9 { font-size: 2.46857em; }
.katex .sizing.reset-size3.size10, .katex .fontsize-ensurer.reset-size3.size10 { font-size: 2.96286em; }
.katex .sizing.reset-size3.size11, .katex .fontsize-ensurer.reset-size3.size11 { font-size: 3.55429em; }
.katex .sizing.reset-size4.size1, .katex .fontsize-ensurer.reset-size4.size1 { font-size: 0.625em; }
.katex .sizing.reset-size4.size2, .katex .fontsize-ensurer.reset-size4.size2 { font-size: 0.75em; }
.katex .sizing.reset-size4.size3, .katex .fontsize-ensurer.reset-size4.size3 { font-size: 0.875em; }
.katex .sizing.reset-size4.size4, .katex .fontsize-ensurer.reset-size4.size4 { font-size: 1em; }
.katex .sizing.reset-size4.size5, .katex .fontsize-ensurer.reset-size4.size5 { font-size: 1.125em; }
.katex .sizing.reset-size4.size6, .katex .fontsize-ensurer.reset-size4.size6 { font-size: 1.25em; }
.katex .sizing.reset-size4.size7, .katex .fontsize-ensurer.reset-size4.size7 { font-size: 1.5em; }
.katex .sizing.reset-size4.size8, .katex .fontsize-ensurer.reset-size4.size8 { font-size: 1.8em; }
.katex .sizing.reset-size4.size9, .katex .fontsize-ensurer.reset-size4.size9 { font-size: 2.16em; }
.katex .sizing.reset-size4.size10, .katex .fontsize-ensurer.reset-size4.size10 { font-size: 2.5925em; }
.katex .sizing.reset-size4.size11, .katex .fontsize-ensurer.reset-size4.size11 { font-size: 3.11em; }
.katex .sizing.reset-size5.size1, .katex .fontsize-ensurer.reset-size5.size1 { font-size: 0.555556em; }
.katex .sizing.reset-size5.size2, .katex .fontsize-ensurer.reset-size5.size2 { font-size: 0.666667em; }
.katex .sizing.reset-size5.size3, .katex .fontsize-ensurer.reset-size5.size3 { font-size: 0.777778em; }
.katex .sizing.reset-size5.size4, .katex .fontsize-ensurer.reset-size5.size4 { font-size: 0.888889em; }
.katex .sizing.reset-size5.size5, .katex .fontsize-ensurer.reset-size5.size5 { font-size: 1em; }
.katex .sizing.reset-size5.size6, .katex .fontsize-ensurer.reset-size5.size6 { font-size: 1.11111em; }
.katex .sizing.reset-size5.size7, .katex .fontsize-ensurer.reset-size5.size7 { font-size: 1.33333em; }
.katex .sizing.reset-size5.size8, .katex .fontsize-ensurer.reset-size5.size8 { font-size: 1.6em; }
.katex .sizing.reset-size5.size9, .katex .fontsize-ensurer.reset-size5.size9 { font-size: 1.92em; }
.katex .sizing.reset-size5.size10, .katex .fontsize-ensurer.reset-size5.size10 { font-size: 2.30444em; }
.katex .sizing.reset-size5.size11, .katex .fontsize-ensurer.reset-size5.size11 { font-size: 2.76444em; }
.katex .sizing.reset-size6.size1, .katex .fontsize-ensurer.reset-size6.size1 { font-size: 0.5em; }
.katex .sizing.reset-size6.size2, .katex .fontsize-ensurer.reset-size6.size2 { font-size: 0.6em; }
.katex .sizing.reset-size6.size3, .katex .fontsize-ensurer.reset-size6.size3 { font-size: 0.7em; }
.katex .sizing.reset-size6.size4, .katex .fontsize-ensurer.reset-size6.size4 { font-size: 0.8em; }
.katex .sizing.reset-size6.size5, .katex .fontsize-ensurer.reset-size6.size5 { font-size: 0.9em; }
.katex .sizing.reset-size6.size6, .katex .fontsize-ensurer.reset-size6.size6 { font-size: 1em; }
.katex .sizing.reset-size6.size7, .katex .fontsize-ensurer.reset-size6.size7 { font-size: 1.2em; }
.katex .sizing.reset-size6.size8, .katex .fontsize-ensurer.reset-size6.size8 { font-size: 1.44em; }
.katex .sizing.reset-size6.size9, .katex .fontsize-ensurer.reset-size6.size9 { font-size: 1.728em; }
.katex .sizing.reset-size6.size10, .katex .fontsize-ensurer.reset-size6.size10 { font-size: 2.074em; }
.katex .sizing.reset-size6.size11, .katex .fontsize-ensurer.reset-size6.size11 { font-size: 2.488em; }
.katex .sizing.reset-size7.size1, .katex .fontsize-ensurer.reset-size7.size1 { font-size: 0.416667em; }
.katex .sizing.reset-size7.size2, .katex .fontsize-ensurer.reset-size7.size2 { font-size: 0.5em; }
.katex .sizing.reset-size7.size3, .katex .fontsize-ensurer.reset-size7.size3 { font-size: 0.583333em; }
.katex .sizing.reset-size7.size4, .katex .fontsize-ensurer.reset-size7.size4 { font-size: 0.666667em; }
.katex .sizing.reset-size7.size5, .katex .fontsize-ensurer.reset-size7.size5 { font-size: 0.75em; }
.katex .sizing.reset-size7.size6, .katex .fontsize-ensurer.reset-size7.size6 { font-size: 0.833333em; }
.katex .sizing.reset-size7.size7, .katex .fontsize-ensurer.reset-size7.size7 { font-size: 1em; }
.katex .sizing.reset-size7.size8, .katex .fontsize-ensurer.reset-size7.size8 { font-size: 1.2em; }
.katex .sizing.reset-size7.size9, .katex .fontsize-ensurer.reset-size7.size9 { font-size: 1.44em; }
.katex .sizing.reset-size7.size10, .katex .fontsize-ensurer.reset-size7.size10 { font-size: 1.72833em; }
.katex .sizing.reset-size7.size11, .katex .fontsize-ensurer.reset-size7.size11 { font-size: 2.07333em; }
.katex .sizing.reset-size8.size1, .katex .fontsize-ensurer.reset-size8.size1 { font-size: 0.347222em; }
.katex .sizing.reset-size8.size2, .katex .fontsize-ensurer.reset-size8.size2 { font-size: 0.416667em; }
.katex .sizing.reset-size8.size3, .katex .fontsize-ensurer.reset-size8.size3 { font-size: 0.486111em; }
.katex .sizing.reset-size8.size4, .katex .fontsize-ensurer.reset-size8.size4 { font-size: 0.555556em; }
.katex .sizing.reset-size8.size5, .katex .fontsize-ensurer.reset-size8.size5 { font-size: 0.625em; }
.katex .sizing.reset-size8.size6, .katex .fontsize-ensurer.reset-size8.size6 { font-size: 0.694444em; }
.katex .sizing.reset-size8.size7, .katex .fontsize-ensurer.reset-size8.size7 { font-size: 0.833333em; }
.katex .sizing.reset-size8.size8, .katex .fontsize-ensurer.reset-size8.size8 { font-size: 1em; }
.katex .sizing.reset-size8.size9, .katex .fontsize-ensurer.reset-size8.size9 { font-size: 1.2em; }
.katex .sizing.reset-size8.size10, .katex .fontsize-ensurer.reset-size8.size10 { font-size: 1.44028em; }
.katex .sizing.reset-size8.size11, .katex .fontsize-ensurer.reset-size8.size11 { font-size: 1.72778em; }
.katex .sizing.reset-size9.size1, .katex .fontsize-ensurer.reset-size9.size1 { font-size: 0.289352em; }
.katex .sizing.reset-size9.size2, .katex .fontsize-ensurer.reset-size9.size2 { font-size: 0.347222em; }
.katex .sizing.reset-size9.size3, .katex .fontsize-ensurer.reset-size9.size3 { font-size: 0.405093em; }
.katex .sizing.reset-size9.size4, .katex .fontsize-ensurer.reset-size9.size4 { font-size: 0.462963em; }
.katex .sizing.reset-size9.size5, .katex .fontsize-ensurer.reset-size9.size5 { font-size: 0.520833em; }
.katex .sizing.reset-size9.size6, .katex .fontsize-ensurer.reset-size9.size6 { font-size: 0.578704em; }
.katex .sizing.reset-size9.size7, .katex .fontsize-ensurer.reset-size9.size7 { font-size: 0.694444em; }
.katex .sizing.reset-size9.size8, .katex .fontsize-ensurer.reset-size9.size8 { font-size: 0.833333em; }
.katex .sizing.reset-size9.size9, .katex .fontsize-ensurer.reset-size9.size9 { font-size: 1em; }
.katex .sizing.reset-size9.size10, .katex .fontsize-ensurer.reset-size9.size10 { font-size: 1.20023em; }
.katex .sizing.reset-size9.size11, .katex .fontsize-ensurer.reset-size9.size11 { font-size: 1.43981em; }
.katex .sizing.reset-size10.size1, .katex .fontsize-ensurer.reset-size10.size1 { font-size: 0.24108em; }
.katex .sizing.reset-size10.size2, .katex .fontsize-ensurer.reset-size10.size2 { font-size: 0.289296em; }
.katex .sizing.reset-size10.size3, .katex .fontsize-ensurer.reset-size10.size3 { font-size: 0.337512em; }
.katex .sizing.reset-size10.size4, .katex .fontsize-ensurer.reset-size10.size4 { font-size: 0.385728em; }
.katex .sizing.reset-size10.size5, .katex .fontsize-ensurer.reset-size10.size5 { font-size: 0.433944em; }
.katex .sizing.reset-size10.size6, .katex .fontsize-ensurer.reset-size10.size6 { font-size: 0.48216em; }
.katex .sizing.reset-size10.size7, .katex .fontsize-ensurer.reset-size10.size7 { font-size: 0.578592em; }
.katex .sizing.reset-size10.size8, .katex .fontsize-ensurer.reset-size10.size8 { font-size: 0.694311em; }
.katex .sizing.reset-size10.size9, .katex .fontsize-ensurer.reset-size10.size9 { font-size: 0.833173em; }
.katex .sizing.reset-size10.size10, .katex .fontsize-ensurer.reset-size10.size10 { font-size: 1em; }
.katex .sizing.reset-size10.size11, .katex .fontsize-ensurer.reset-size10.size11 { font-size: 1.19961em; }
.katex .sizing.reset-size11.size1, .katex .fontsize-ensurer.reset-size11.size1 { font-size: 0.200965em; }
.katex .sizing.reset-size11.size2, .katex .fontsize-ensurer.reset-size11.size2 { font-size: 0.241158em; }
.katex .sizing.reset-size11.size3, .katex .fontsize-ensurer.reset-size11.size3 { font-size: 0.28135em; }
.katex .sizing.reset-size11.size4, .katex .fontsize-ensurer.reset-size11.size4 { font-size: 0.321543em; }
.katex .sizing.reset-size11.size5, .katex .fontsize-ensurer.reset-size11.size5 { font-size: 0.361736em; }
.katex .sizing.reset-size11.size6, .katex .fontsize-ensurer.reset-size11.size6 { font-size: 0.401929em; }
.katex .sizing.reset-size11.size7, .katex .fontsize-ensurer.reset-size11.size7 { font-size: 0.482315em; }
.katex .sizing.reset-size11.size8, .katex .fontsize-ensurer.reset-size11.size8 { font-size: 0.578778em; }
.katex .sizing.reset-size11.size9, .katex .fontsize-ensurer.reset-size11.size9 { font-size: 0.694534em; }
.katex .sizing.reset-size11.size10, .katex .fontsize-ensurer.reset-size11.size10 { font-size: 0.833601em; }
.katex .sizing.reset-size11.size11, .katex .fontsize-ensurer.reset-size11.size11 { font-size: 1em; }
.katex .delimsizing.size1 { font-family: KaTeX_Size1; }
.katex .delimsizing.size2 { font-family: KaTeX_Size2; }
.katex .delimsizing.size3 { font-family: KaTeX_Size3; }
.katex .delimsizing.size4 { font-family: KaTeX_Size4; }
.katex .delimsizing.mult .delim-size1 > span { font-family: KaTeX_Size1; }
.katex .delimsizing.mult .delim-size4 > span { font-family: KaTeX_Size4; }
.katex .nulldelimiter { display: inline-block; width: 0.12em; }
.katex .delimcenter { position: relative; }
.katex .op-symbol { position: relative; }
.katex .op-symbol.small-op { font-family: KaTeX_Size1; }
.katex .op-symbol.large-op { font-family: KaTeX_Size2; }
.katex .op-limits > .vlist-t { text-align: center; }
.katex .accent > .vlist-t { text-align: center; }
.katex .accent .accent-body:not(.accent-full) { width: 0px; }
.katex .accent .accent-body { position: relative; }
.katex .overlay { display: block; }
.katex .mtable .vertical-separator { display: inline-block; margin: 0px -0.025em; border-right: 0.05em solid; }
.katex .mtable .vs-dashed { border-right: 0.05em dashed; }
.katex .mtable .arraycolsep { display: inline-block; }
.katex .mtable .col-align-c > .vlist-t { text-align: center; }
.katex .mtable .col-align-l > .vlist-t { text-align: left; }
.katex .mtable .col-align-r > .vlist-t { text-align: right; }
.katex .svg-align { text-align: left; }
.katex svg, .screenShotTempCanvas { display: block; position: absolute; width: 100%; height: inherit; fill: currentcolor; stroke: currentcolor; fill-rule: nonzero; fill-opacity: 1; stroke-width: 1; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0; stroke-opacity: 1; }
.katex svg path { stroke: none; }
.katex .stretchy { width: 100%; display: block; position: relative; overflow: hidden; }
.katex .stretchy::before, .katex .stretchy::after { content: ""; }
.katex .hide-tail { width: 100%; position: relative; overflow: hidden; }
.katex .halfarrow-left { position: absolute; left: 0px; width: 50.2%; overflow: hidden; }
.katex .halfarrow-right { position: absolute; right: 0px; width: 50.2%; overflow: hidden; }
.katex .brace-left { position: absolute; left: 0px; width: 25.1%; overflow: hidden; }
.katex .brace-center { position: absolute; left: 25%; width: 50%; overflow: hidden; }
.katex .brace-right { position: absolute; right: 0px; width: 25.1%; overflow: hidden; }
.katex .x-arrow-pad { padding: 0px 0.5em; }
.katex .x-arrow, .katex .mover, .katex .munder { text-align: center; }
.katex .boxpad { padding: 0px 0.3em; }
.katex .fbox { box-sizing: border-box; border: 0.04em solid black; }
.katex .fcolorbox { box-sizing: border-box; border: 0.04em solid; }
.katex .cancel-pad { padding: 0px 0.2em; }
.katex .cancel-lap { margin-left: -0.2em; margin-right: -0.2em; }
.katex .sout { border-bottom-style: solid; border-bottom-width: 0.08em; }
.output_wrapper pre code { display: -webkit-box !important; }
.output_wrapper .hljs{color: rgb(169, 183, 198); background: rgb(40, 43, 46); display: block; overflow-x: auto; padding: 0.5em;}

.output_wrapper .hljs-params{color: rgb(255, 152, 35);}

.output_wrapper .hljs-number,.output_wrapper .hljs-literal,.output_wrapper .hljs-symbol,.output_wrapper .hljs-bullet{color: rgb(174, 135, 250);}

.output_wrapper .hljs-function,.output_wrapper .hljs-built_in,.output_wrapper .hljs-name,.output_wrapper .hljs-keyword,.output_wrapper .hljs-selector-tag,.output_wrapper .hljs-deletion{color: rgb(248, 35, 117);}

.output_wrapper .hljs-variable,.output_wrapper .hljs-template-variable,.output_wrapper .hljs-link{color: rgb(98, 151, 85);}

.output_wrapper .hljs-comment,.output_wrapper .hljs-quote{color: rgb(128, 128, 128);}

.output_wrapper .hljs-meta{color: rgb(91, 218, 237);}

.output_wrapper .hljs-string,.output_wrapper .hljs-attribute,.output_wrapper .hljs-addition{color: rgb(238, 220, 112);}

.output_wrapper .hljs-attr,.output_wrapper .hljs-section,.output_wrapper .hljs-title,.output_wrapper .hljs-type{color: rgb(165, 218, 45);}

.output_wrapper .hljs-selector-class{color: rgb(165, 218, 45);}

.output_wrapper .hljs-emphasis{font-style: italic;}

.output_wrapper .hljs-strong{font-weight: bold;}

.output_wrapper pre code {line-height: 18px; font-size: 14px; font-weight: normal; word-spacing: 0px; letter-spacing: 0px;}
.output_wrapper{font-size: 16px; color: rgb(62, 62, 62); line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;}

.output_wrapper *{font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px;}

.output_wrapper p{margin: 1.5em 0px;}

.output_wrapper h1,.output_wrapper h2,.output_wrapper h3,.output_wrapper h4,.output_wrapper h5,.output_wrapper h6{margin: 1.5em 0px; font-weight: bold; color: rgb(21, 153, 87);}

.output_wrapper h1{font-size: 1.6em;}

.output_wrapper h2{font-size: 1.4em;}

.output_wrapper h3{font-size: 1.3em;}

.output_wrapper h4{font-size: 1.2em;}

.output_wrapper h5{font-size: 1em;}

.output_wrapper h6{font-size: 1em;}

.output_wrapper ul,.output_wrapper ol{padding-left: 32px;}

.output_wrapper ul{list-style-type: disc;}

.output_wrapper ol{list-style-type: decimal;}

.output_wrapper li *{}

.output_wrapper li{margin-bottom: 0.5em;}

.output_wrapper .code_size_default{line-height: 18px; font-size: 14px; font-weight: normal; word-spacing: 0px; letter-spacing: 0px;}

.output_wrapper .code_size_tight{line-height: 15px; font-size: 11px; font-weight: normal; word-spacing: -3px; letter-spacing: 0px;}

.output_wrapper pre code{font-family: Consolas, Inconsolata, Courier, monospace; border-radius: 0px;}

.output_wrapper blockquote{display: block; padding: 15px 15px 15px 1rem; font-size: 0.9em; margin: 1em 0px; color: rgb(129, 145, 152); border-left: 6px solid rgb(220, 230, 240); background: rgb(242, 247, 251); overflow: auto; overflow-wrap: normal; word-break: normal;}

.output_wrapper blockquote p{margin: 0px;}

.output_wrapper a{text-decoration: none; color: rgb(30, 107, 184); overflow-wrap: break-word;}

.output_wrapper strong{font-weight: bold;}

.output_wrapper em{font-style: italic;}

.output_wrapper del{font-style: italic;}

.output_wrapper strong em{font-weight: bold;}

.output_wrapper hr{height: 1px; margin: 1.5rem 0px; border-right: none; border-bottom: none; border-left: none; border-image: initial; border-top: 1px dashed rgb(165, 165, 165);}

.output_wrapper code{overflow-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0px 2px; color: rgb(233, 105, 0); background: rgb(248, 248, 248);}

.output_wrapper img{display: block; margin: 0px auto; max-width: 100%;}

.output_wrapper figcaption{margin-top: 10px; text-align: center; color: rgb(153, 153, 153); font-size: 0.7em;}

.output_wrapper table{display: table; width: 100%; text-align: left;}

.output_wrapper tbody{border: 0px;}

.output_wrapper table tr{border-width: 1px 0px 0px; border-right-style: initial; border-bottom-style: initial; border-left-style: initial; border-right-color: initial; border-bottom-color: initial; border-left-color: initial; border-image: initial; border-top-style: solid; border-top-color: rgb(204, 204, 204); background-color: white;}

.output_wrapper table tr th,.output_wrapper table tr td{font-size: 1em; border: 1px solid rgb(204, 204, 204); padding: 0.5em 1em; text-align: left;}

.output_wrapper table tr th{font-weight: bold; background-color: rgb(240, 240, 240);}

.output_wrapper .katex-display{font-size: 1.22em;}

.output_wrapper .katex{padding: 8px 3px;}

.output_wrapper .katex-display > .katex{display: inline-block; text-align: center; padding: 3px;}

.output_wrapper .katex img{display: inline-block; vertical-align: middle;}

.output_wrapper a[href^="#"] sup{vertical-align: super; margin: 0px 2px; padding: 1px 3px; color: rgb(255, 255, 255); background: rgb(102, 102, 102); font-size: 0.7em;}

.output_wrapper .task-list-list{list-style-type: none;}

.output_wrapper .task-list-list.checked{color: rgb(62, 62, 62);}

.output_wrapper .task-list-list.uncheck{color: rgb(191, 193, 191);}

.output_wrapper .task-list-list .icon_uncheck,.output_wrapper .task-list-list .icon_check{display: inline-block; vertical-align: middle; margin-right: 10px;}

.output_wrapper .task-list-list .icon_check::before{content: "√"; border: 2px solid rgb(62, 62, 62); color: red;}

.output_wrapper .task-list-list .icon_uncheck::before{content: "x"; border: 2px solid rgb(191, 193, 191); color: rgb(191, 193, 191);}

.output_wrapper .task-list-list .icon_check::before,.output_wrapper .task-list-list .icon_uncheck::before{padding: 2px 8px 2px 5px; border-radius: 5px;}

.output_wrapper .toc{margin-left: 25px;}

.output_wrapper .toc_item{display: block;}

.output_wrapper .toc_left{margin-left: 25px;}
-->

公众号:小李不秃,Java 原创博主
阅读本文大概需要 7.8 分钟

前言什么是 JSON为什么有 JSON如何使用 JSONJSON 的数据结构Json 在 javaScript 中的使用操作 Json 对象操作 JSON 数组JSON.parse()JSON.stringify()evalJson 在 Java 中的使用Json-libGsonJacksonfastJson总结参考推荐阅读

前言

我们在进行软件开发的过程中,服务与服务之间会进行相互的调用。在数据进行传输前,我们通常会将数据转化成 JSON 的格式进行传输,比如 ajax 调用请求,接收传过来的 JSON 数据,javascript 就可以对传过来的数据进行直接的调用。

本篇文章会讲解以下的内容:

  • 什么是 JSON---what
  • 为什么有 JSON---why
  • 如何使用 JSON---How
    • JSON 的数据结构
    • Json 在 javascript 中的使用
    • Json 在 Java 中的使用

什么是 JSON

JSON 全拼 Java Script Object Notation,JavaScript 对象表示法。是一种由道格拉斯·克罗克福特构想和设计、轻量级的数据交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管 JSON 是 JavaScript 的子集,但是 JSON 是独立于语言的文本格式。

JSON 数据格式与语言无关。即便它源自 JavaScript,但很多编程语言都支持 JSON 格式数据的生成和解析,例如在 Java 中就有 fastjson、gson 等工具类对 JSON 进行操作。

小结

  • JSON 是数据交换语言。
  • JSON 是独立于任何程序语言的文本格式。

为什么有 JSON

提到这里,就不得不和 XML 进行比较了。XML 也是可以作为跨平台的数据交换格式。但是为什么我们大多用 JSON,而不用 XML 呢?有下面几点原因:

  • javaScript 原生支持 JSON,解析速度更快。而 XML 解析成 DOM 对象的时候,浏览器会有差异。

  • 对于 AJAX 应用程序来说,JSON 比 XML 更快更易使用。

  • 使用 XML :读取 XML 文档,使用 XML DOM 循环遍历文档,将读取值存入变量。

  • 使用 JSON:读取 JSON 字符串,JSON.parse 解析 JSON 字符串。

综上,我们更倾向于选择 JSON 来进行数据交换。

如何使用 JSON

JSON 的数据结构

  • 对象

JSON 对象使用在 大括号“{}”中书写,对象可以有多个键值对(key/value)。

key 必须是字符串,value 可以是合法的 JSON 数据类型(字符串、数字、对象、数组、布尔值或null)

key 和 value 中使用冒号“:”分割,键值对之间用逗号“,”分割。

{"name":"关注公众号:小李不秃","age":18,"money":null}
  • 数组

JSON 数组在中括号“[]”中书写。JSON 中数组值必须是合法的 JSON 数据类型。

[    
    {"name":"张三"},
    {"name":"李四"),
    {"name":"王五"}
]

Json 在 javaScript 中的使用

操作 Json 对象

  • 访问对象值

可以使用点号“.”来访问对象的值,也可以使用中括号“[]”来访问对象的值。

var data, x;
data = {"name":"xiaoli", "area":"china", "money":null};
x = data.name; #或者myObj["name"] 运行结果:xiaoli
  • 循环对象

使用 for-in 来循环对象的属性

var data, x;
data = {"name":"xiaoli", "area":"china", "money":null};
for(x in data){
    console.log(x + ":" + data[x]);
} 运行结果:
name:xiaoli
area:china 
money:null
  • 修改值

可以使用点号“.”来修改 JSON 对象的值,也可以使用中括号“[]”修改 JSON 对象的值。

data.money = 100;
data["money"] = 100;
  • 删除值

通过 delete 关键字来删除 JSON 对象的属性。

delete data.money;
delete data["money"]

操作 JSON 数组

  • 访问 JSON 数组值

通过索引值来访问数组。

var myObj, x;
myObj = {
    "name":"网站",
    "num":3,
    "sites":[ "Google", "Runoob", "Taobao" ]
}
x = myObj.sites[0]; 运行结果:Google
  • 循环数组

通过 for-in 来访问数组。

var myObj, i, x = "";
myObj = {
    "name":"网站",
    "num":3,
    "sites":[ "Google", "Runoob", "Taobao" ]
}; for (i in myObj.sites) {
    x += myObj.sites[i] + "<br>";
} 运行结果: Google
Runoob
Taobao

也可以通过 for 来循环访问数组。

var myObj, i, x = "";
myObj = {
    "name":"网站",
    "num":3,
    "sites":[ "Google", "Runoob", "Taobao" ]
}; for (i = 0; i < myObj.sites.length; i++) {
    x += myObj.sites[i] + "<br>";
}

javaScript 中的 for-in 类似于 Java 中的 foreach 。

  • 修改数组元素

可以通过索引值来修改数组元素。

myObj.sites[1] = "Github";
  • 删除数组元素

使用 delete 来删除数组元素

delete myObj.sites[1];

这里需要注意 delete 并没有彻底删除元素,而是删除它的值,仍然会保留空间。运算符 delete 只是将该值设置为 undefined,而不会影响数组的长度。如果想要实现彻底删除,需要使用 splice() 方法。

var myObj, i, x = "";
myObj = {
    "name":"网站",
    "num":3,
    "sites":[ "Google", "Runoob", "Taobao" ]
};
delete myObj.sites[1]; x = "sites.length = " + myObj.sites.length + "<br><br>"; for (i=0;i<myObj.sites.length;i++) {
    console.log(i + ":" + myObj.sites[i]);
    x += i + " " + myObj.sites[i] + "<br>";
} document.getElementById("demo").innerHTML = x; 运行结果:
0:Google
1:undefined
2:Taobao
myObj.sites.splice(1,1);

运行结果:
0:Google
1:Taobao

JSON.parse()

JSON 通常与服务端交换数据,接收服务器传输的数据时一般是字符串,我们可以通过 JSON.parse() 方法将数据转换为 JavaScipt 对象。

具体使用

var obj = JSON.parse('{"name":"关注公众号:小李不秃","age":18,"money":null}');
console.log(obj.name + ":" + obj.age + ":" + obj.money) 运行结果:关注公众号:小李不秃:18:null

JSON 存 Date 对象,需要将其转换为字符串,之后再将字符串转换为 Date 对象。

var text = '{ "name":"小李不秃", "initDate":"2020-1-17"}';
var obj = JSON.parse(text, function (key, value) {
    if (key == "initDate") {
        return new Date(value);
    } else {
        return value;
}}); console.log(obj.name + ":" + obj.initDate); 运行结果:小李不秃:Fri Jan 17 2020 00:00:00 GMT+0800 (中国标准时间)

JSON.stringify()

JSON 在向服务端传输的数据一般是字符串,所以我们可以使用 JSON.stringify() 方法将 JavaScript 对象转换为字符串。

具体使用

var obj = {"name":"xiaoli", "area":"china", "money":null};
console.log(obj);
var myJSON = JSON.stringify(obj);
console.log(myJSON);

运行结果

eval

对于服务器返回的 JSON 字符串,如果 jQuery 异步请求没做类型说明,或者以字符串方式接收,那么需要做一次对象化处理,方式不是太麻烦,就是将该字符串放于 eval() 中执行一次。这种方式也适合以普通 javascipt 方式获取 json 对象,以下举例说明:

var u = eval('('+user+')');

为什么要 eval 这里要添加 ('('+user+')') 呢?

原因在于:eval 本身的问题。 由于 json 是以 {} 的方式来开始以及结束的,在 js 中,它会被当成一个语句块来处理,所以必须强制性的将它转换成一种表达式。

加上圆括号的目的是迫使 eval 函数在处理 JavaScript 代码的时候强制将括号内的表达式(expression)转化为对象,而不是作为语句(statement)来执行。举一个例子,例如对象字面量 {},如若不加外层的括号,那么 eval 会将大括号识别为 javascript 代码块的开始和结束标记,那么{}将会被认为是执行了一句空语句。所以下面两个执行结果是不同的:

alert(eval("{}"); // return undefined
alert(eval("({})");// return object[Object]

测试用例

var user = '{"name":"关注公众号:小李不秃","age":18,"money":null,'+  
    'showInfo:function(){'+  
    'document.write("姓名:"+this.name+"<br/>");'+  
    'document.write("年龄:"+this.age+"<br/>");'+  
    'document.write("金钱:"+this.money+"<br/>");}}'; 
var u = eval('('+user+')');  
u.showInfo(); 运行结果: 姓名:关注公众号:小李不秃
年龄:18
金钱:null

Json 在 Java 中的使用

在 Java 中,解析 JSON 的第三方工具类有很多,常用的有几种:

  • Json-lib
  • Gson
  • Jackson
  • fastjson

统一用下面的 Person 类作为示例

@Data
public class Person {     private String name;
    private Integer age;     public Person() {
    }     public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

那我们对这几个工具类进行一一介绍:

Json-lib

Json-lib 是一个 Java 类库,提供将 Java 对象(包括:beans,maps,collections,java arrays 和 XML等)和 JSON 互相转换的功能。

引入相关 jar 包

  • commons-io-2.0.1.jar
  • commons-lang-2.5.jar
  • commons-collections-3.1.jar
  • commons-beanutils-1.7.0.jar
  • ezmorph-1.0.3.jar
  • json-lib-2.1-jdk15.jar

Json-lib 工具类

封装一个 Json-lib 工具类,方便测试用。

// Json-lib 工具类
public class JsonLibUtils {
    /**
     * bean 转换为 Json 字符串
     */
    public static String bean2json(Object o){
        JSONObject jsonObject = JSONObject.fromObject(o);
        return jsonObject.toString();
    }
    /**
     * json 转换为 bean
     */
    public static Object json2bean(String s,Class c){
        JSONObject jsonObject = JSONObject.fromObject(s);
        return JSONObject.toBean(jsonObject,c);
    }
    /**
     * list 转换为 Json 字符串
     */
    public static String list2json(List list){
        JSONArray jsonArray = JSONArray.fromObject(list);
        return jsonArray.toString();
    }
    /**
     * json 转换为 list
     */
    public static List json2List(String s){
        return JSONArray.fromObject(s);
    }
    /**
     * set 转换为 Json 字符串
     */
    public static String set2json(Set set){
        JSONArray jsonArray = JSONArray.fromObject(set);
        return jsonArray.toString();
    }     /**
     * json 转换为 set
     */
    public static Set json2Set(String json) {
        Set<Person> set = new HashSet<>(json2List(json));
        return set;
    }
    /**
     * map 转换为 Json 字符串
     */
    public static String map2json(Map map){
        JSONObject jsonObject = JSONObject.fromObject(map);
        return jsonObject.toString();
    }
    /**
     * json 转换为 map
     */
    public static Map<Object, Object> json2Map(String json) {
        JSONObject jsonObject = JSONObject.fromObject(json);
        Map<Object, Object> map = (Map)jsonObject;
        return map;
    }
}

示例代码:

public class JsonlibTest {

    public static void main(String[] args) {
        //1. bean 和 json 互转
        Person person = new Person("xiaoli",18);
        String json = JsonLibUtils.bean2json(person);
        // {"age":18,"name":"xiaoli"}
        Person person2 = (Person)JsonLibUtils.json2bean(json, Person.class);         //2. list 和 json 互转
        List<Person> list = new ArrayList<Person>();
        list.add(new Person("李四",10));
        list.add(new Person("王五",20));
        String listJson = JsonLibUtils.list2json(list);
        // [{"age":10,"name":"李四"},{"age":20,"name":"王五"}]
        List json2List = JsonLibUtils.json2List(listJson);         //3. map 转 json
        Map<String,Person> map = new HashMap<String,Person>();
        map.put("map1",new Person("李四",10));
        map.put("map2",new Person("王五",20));
        String mapJson = JsonLibUtils.map2json(map);
        // {"map2":{"age":20,"name":"王五"},"map1":{"age":10,"name":"李四"}}
        Map<Object, Object> map2 = JsonLibUtils.json2Map(mapJson);         //4. set 与 json 互转
        Set<Person> set = new LinkedHashSet<Person>();
        set.add(new Person("李四",10));
        set.add(new Person("王五",20));
        String setJson = JsonLibUtils.set2json(set);
        // [{"age":10,"name":"李四"},{"age":20,"name":"王五"}]
        JsonLibUtils.json2Set(setJson);
    }
}

缺点

  • 依赖的包过多。
  • 复杂类型的转换有缺陷,比如一个类里面会出现另一个类的list或者map集合,json-lib从json到bean的转换就会出现问题。
  • 不推荐使用 Json-lib 的 n 个理由

小结

json-lib 提供两个对象,分别是 JSONObjectJSONArray,分别对应着 JSON 的两个数据结构。根据需要选取转换的对象。但是由于 json-lib 已经 n 多年没有维护,缺陷较多,在功能和性能方面已经无法满足我们的需求,所以尽量还是不用为好。

Gson

Gson 是 Google 公司发布的一个开源代码的 Java 库,主要用途为序列化 Java 对象为 JSON 字符串,或反序列化 JSON 字符串为 Java 对象。

Gson 提供了 fromJson()toJson() 两个用于解析和生成的方法,前者实现反序列化,后者实现了序列化。

依赖

使用 Gson 需要引入这个依赖。

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
    <scope>compile</scope>
</dependency>

Gson 工具类

封装一些常用方法的转换工具类。

public class GsonUtil {
    /**
     * bean 转换为 Json 字符串
     */
    public static String bean2json(Object object){
        Gson gson = new Gson();
        return gson.toJson(object);
    }
    /**
     * json 转换为 bean
     */
    public static Object json2bean(String json,Class c){
        Gson gson = new Gson();
        return gson.fromJson(json,c);
    }
    /**
     * list 转换为 Json 字符串
     */
    public static String list2json(List list){
        Gson gson = new Gson();
        return gson.toJson(list);
    }
    /**
     * json 转换为 list
     */
    public static List json2List(String json){
        Gson gson = new Gson();
        return gson.fromJson(json,new TypeToken<List>(){}.getType());
    }
    /**
     * set 转换为 Json 字符串
     */
    public static String set2json(Set set){
        Gson gson = new Gson();
        return  gson.toJson(set);
    }
    /**
     * json 转换为 set
     */
    public static Set json2Set(String json){
        Gson gson = new Gson();
        return gson.fromJson(json,new TypeToken<Set>(){}.getType());
    }
    /**
     * map 转换为 Json 字符串
     */
    public static String map2json(Map map){
        Gson gson = new Gson();
        return  gson.toJson(map);
    }
    /**
     * json 转换为 map
     */
    public static Map json2Map(String json){
        Gson gson = new Gson();
        return gson.fromJson(json,new TypeToken<Map>(){}.getType());
    }
}

示例代码

public static void main(String[] args) {
    //1. bean 和 json 互转
    Person person = new Person("xiaoli",18);
    String json = GsonUtil.bean2json(person);
    System.out.println(json);
    Person person2 = (Person)GsonUtil.json2bean(json, Person.class);
    System.out.println(person2.toString());     //2. list 和 json 互转
    List<Person> list = new ArrayList<Person>();
    list.add(new Person("李四",10));
    list.add(new Person("王五",20));
    String listJson = GsonUtil.list2json(list);
    System.out.println(listJson);
    List json2List = GsonUtil.json2List(listJson);
    System.out.println(json2List.toString());     //3. map 转 json
    Map<String,Person> map = new HashMap<String,Person>();
    map.put("map1",new Person("李四",10));
    map.put("map2",new Person("王五",20));
    String mapJson = GsonUtil.map2json(map);
    System.out.println(mapJson);
    Map<Object, Object> map2 = GsonUtil.json2Map(mapJson);
    System.out.println(map2.toString());     //4. set 与 json 互转
    Set<Person> set = new LinkedHashSet<Person>();
    set.add(new Person("李四",10));
    set.add(new Person("王五",20));
    String setJson = GsonUtil.set2json(set);
    System.out.println(setJson);
    Set set1 = GsonUtil.json2Set(setJson);
    System.out.println(set1.toString());
} 运行结果:
{"name":"xiaoli","age":18}
Person(name=xiaoli, age=18)
[{"name":"李四","age":10},{"name":"王五","age":20}]
[{name=李四, age=10.0}, {name=王五, age=20.0}]
{"map2":{"name":"王五","age":20},"map1":{"name":"李四","age":10}}
{map2={name=王五, age=20.0}, map1={name=李四, age=10.0}}
[{"name":"李四","age":10},{"name":"王五","age":20}]
[{name=李四, age=10.0}, {name=王五, age=20.0}]

小结

Gson 是 Google 开发的,所以也是经过了很多的验证。但是将字符串解析为指定的集合类型需要花点信息,因为涉及到了泛型—TypeToken

具体的 Gson 文章详见:Gson使用指南

Jackson

Github 地址:jackson

简单介绍一下 Jackson:

  • Jackson 是基于 Stream 构建的一款用户序列化和反序列化 JSON 的 Java 开源库。
  • 社区活跃,更新速度快。
  • Spring MVC 的默认 JSON 解析器。
  • 擅长处理各种大量数据格式模块。

Jackson 的核心模块由三部分组成。

  • jackson-core,核心包,提供基于「流模式」解析的相关 API,它包括 JsonPaser 和 JsonGenerator。
  • jackson-annotations,注解包,提供标准注解功能。
  • jack-databind,数据绑定包, 提供基于「对象绑定」 解析的相关 API ( ObjectMapper ) 和「树模型」 解析的相关 API (JsonNode);基于「对象绑定」 解析的 API 和「树模型」 解析的 API 依赖基于「流模式」解析的 API。

ObjectMapper 通过 writeValue()的系列方法可以将 Java 对象序列化为 JSON,并将 JSON 存储成不同的格式。

  • String (writeValueAsString)
  • Byte Array (writeValueAsBytes)

ObjectMapper 通过 readValue() 系列方法可以从不同的数据源(String、Bytes)将 JSON 反序列化为 Java 对象。

依赖

使用 Jackson 之前,需要先添加依赖。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.1</version>
</dependency>

Jackson 工具类

public class JacksonUtil {
    private static ObjectMapper mapper = null;
    /**
     * bean 转换为 Json 字符串
     */
    public static String bean2json(Object object){
        mapper = new ObjectMapper();
        try {
            return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * json 转换为 bean
     */
    public static Object json2bean(String json,Class c){
        mapper = new ObjectMapper();
        try {
            return mapper.readValue(json,c);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * list 转换为 Json 字符串
     */
    public static String list2json(List list){
        mapper = new ObjectMapper();
        try {
            return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * json 转换为 list
     */
    public static List json2List(String json){
        mapper = new ObjectMapper();
        try {
            return mapper.readValue(json,List.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * set 转换为 Json 字符串
     */
    public static String set2json(Set set){
        mapper = new ObjectMapper();
        try {
            return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(set);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * json 转换为 set
     */
    public static Set json2Set(String json){
        mapper = new ObjectMapper();
        try {
            return mapper.readValue(json,Set.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * map 转换为 Json 字符串
     */
    public static String map2json(Map map){
        mapper = new ObjectMapper();
        try {
            return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(map);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * json 转换为 map
     */
    public static Map json2Map(String json){
        mapper = new ObjectMapper();
        try {
            return mapper.readValue(json,Map.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

示例代码

public static void main(String[] args) {
    //1. bean 和 json 互转
    Person person = new Person("xiaoli",18);
    String json = JacksonUtil.bean2json(person);
    System.out.println(json);
    Person person2 = (Person)JacksonUtil.json2bean(json, Person.class);
    System.out.println(person2.toString());     //2. list 和 json 互转
    List<Person> list = new ArrayList<Person>();
    list.add(new Person("李四",10));
    list.add(new Person("王五",20));
    String listJson = JacksonUtil.list2json(list);
    System.out.println(listJson);
    List json2List = JacksonUtil.json2List(listJson);
    System.out.println(json2List.toString());     //3. map 转 json
    Map<String,Person> map = new HashMap<String,Person>();
    map.put("map1",new Person("李四",10));
    map.put("map2",new Person("王五",20));
    String mapJson = JacksonUtil.map2json(map);
    System.out.println(mapJson);
    Map<Object, Object> map2 = JacksonUtil.json2Map(mapJson);
    System.out.println(map2.toString());     //4. set 与 json 互转
    Set<Person> set = new LinkedHashSet<Person>();
    set.add(new Person("李四",10));
    set.add(new Person("王五",20));
    String setJson = JacksonUtil.set2json(set);
    System.out.println(setJson);
    Set set1 = JacksonUtil.json2Set(setJson);
    System.out.println(set1.toString());
}

缺点

  • Jackson对于复杂类型的json转换bean会出现问题,一些集合Map,List的转换出现问题。
  • Jackson对于复杂类型的bean转换Json,转换的json格式不是标准的Json格式。

上面两个缺点有待考察,如有具体例子会进行更新。

小结:

Jackson 可以通过 ObjectMapper 的 writeValue()readValue() 系列方法对 JSON 进行序列化和反序列化。并且擅长处理各种大量数据格式模块。

具体 Jackson 文章详见:https://www.cnblogs.com/cnjavahome/p/8393178.html

fastJson

FastJson 是由阿里巴巴开源的 JSON 解析库,它可以进行快速的序列化和反序列化。功能还是很强大的。使用 fastjson 需要注意,转换的类必须有默认的无参构造函数。

Github:fastjson

fastjson 对于 JSON 字符串解析主要用到了下面三个类:

  • JSON:fastjson 的解析器,提供 toJSONStringparseObject 方法对 JSON 进行序列化和反序列化。
  • JSONObject:fastjson 提供的 json 对象。
  • JSONArray:fastjson 提供的 json 数组对象。

依赖

使用 fastjson 前,需要引入相关依赖。

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.61</version>
</dependency>

fastjson 工具类

public class FastJsonUtil{
    /**
     * bean 转换为 Json 字符串
     */
    public static String bean2json(Object object){
        return JSON.toJSONString(object);
    }
    /**
     * json 转换为 bean
     */
    public static Object json2bean(String json,Class c){
        return JSON.parseObject(json,c);
    }
    /**
     * list 转换为 Json 字符串
     */
    public static String list2json(List list){
        return JSON.toJSONString(list);
    }
    /**
     * json 转换为 list
     */
    public static List json2List(String json,Class c){
        return JSON.parseArray(json,c);
    }
    /**
     * set 转换为 Json 字符串
     */
    public static String set2json(Set set){
        return  JSON.toJSONString(set);
    }
    /**
     * json 转换为 set
     */
    public static Set json2Set(String json){
        return JSON.parseObject(json,Set.class);
    }
    /**
     * map 转换为 Json 字符串
     */
    public static String map2json(Map map){
        return  JSON.toJSONString(map);
    }
    /**
     * json 转换为 map
     */
    public static Map json2Map(String json){
        return JSON.parseObject(json);
    }
}

实例代码

public class FastJsonTest {
    public static void main(String[] args) {
        //1. bean 和 json 互转
        Person person = new Person("xiaoli",18);
        String json = FastJsonUtil.bean2json(person);
        System.out.println(json);
        Person person2 = (Person)FastJsonUtil.json2bean(json, Person.class);
        System.out.println(person2.toString());
        //2. list 和 json 互转
        List<Person> list = new ArrayList<Person>();
        list.add(new Person("李四",10));
        list.add(new Person("王五",20));
        String listJson = FastJsonUtil.list2json(list);
        System.out.println(listJson);
        List json2List = FastJsonUtil.json2List(listJson, Person.class);
        System.out.println(json2List.toString());         //3. map 转 json
        Map<String,Person> map = new HashMap<String,Person>();
        map.put("map1",new Person("李四",10));
        map.put("map2",new Person("王五",20));
        String mapJson = FastJsonUtil.map2json(map);
        System.out.println(mapJson);
        Map<Object, Object> map2 = FastJsonUtil.json2Map(mapJson);
        System.out.println(map2.toString());         //4. set 与 json 互转
        Set<Person> set = new LinkedHashSet<Person>();
        set.add(new Person("李四",10));
        set.add(new Person("王五",20));
        String setJson = FastJsonUtil.set2json(set);
        System.out.println(setJson);
        Set set1 = FastJsonUtil.json2Set(setJson);
        System.out.println(set1.toString());
    }
} 运行结果:
{"age":18,"name":"xiaoli"}
Person(name=xiaoli, age=18)
[{"age":10,"name":"李四"},{"age":20,"name":"王五"}]
[Person(name=李四, age=10), Person(name=王五, age=20)]
{"map2":{"age":20,"name":"王五"},"map1":{"age":10,"name":"李四"}}
{"map2":{"name":"王五","age":20},"map1":{"name":"李四","age":10}}
[{"age":10,"name":"李四"},{"age":20,"name":"王五"}]
[{"name":"王五","age":20}, {"name":"李四","age":10}]

小结

fastjson 虽然很快,我还是挺推荐使用的,但还是有些缺点的。具体详见:fastjson这么快老外为啥还是热衷 jackson?

总结

我们对本篇文章做个总结:

什么是 JSON:数据交互语言,独立于任何程序语言的文本格式。

为什么使用 JSON:javaScript 原生支持 JSON,解析速度更快;比 xml 更易使用。

如何使用 JSON:

  • 了解了 JSON 的数据结构:对象和数组。
  • Json 在 javaScript 中的使用:操作 json 对象和数组,通过 parse()stringift() 实现 json 的反序列化和序列化。
  • Json 在 Java 中的使用:介绍了 Json-lib、Gson、Jackson 和 fastjson,并且对这些工具常用的序列化和反序列化的实现进行了封装。

对此,我们了解了 JSON,并且会对 JSON 进行序列化和反序列化。

参考

推荐阅读

JSON的学习与使用的更多相关文章

  1. JSON 教程学习进度备忘

    书签:跳过:另外跳过的内容有待跟进 __________________ 学习资源:W3School. _________________ 跳过的内容: 1. ______________ 知识点:1 ...

  2. Json.Net学习笔记

    http://www.cnblogs.com/xiaojinhe2/archive/2011/10/28/2227789.html Newtonsoft.Json(Json.Net)学习笔记 http ...

  3. Newtonsoft.Json(Json.Net)学习

    转自原文 Newtonsoft.Json(Json.Net)学习笔记 Newtonsoft.Json,一款.NET中开源的Json序列化和反序列化类库.软件下载地址: http://www.newto ...

  4. Android之Json的学习

    json数据包含json对象,json数组,对象是{ },数组是[ ], 数组里面还可以包含json对象,json对象之间是用逗号(,)隔开 形式如下: { "languages" ...

  5. Newtonsoft.Json(Json.Net)学习笔记

    Newtonsoft.Json 在Vs2013中就有自带的: 下面是Json序列化和反序列化的简单封装: /// <summary> /// Json帮助类 /// </summar ...

  6. JSON入门学习

    JSON是一种与开发语言无关的轻量级的数据格式(JavaScript Object Notation) 优点:易于阅读和编写,易于程序解析和生产 JSON数据格式中没有日期及时间的数据格式的.一般直接 ...

  7. json官方学习档案

    项目经常用json开发,但说实话,对json了解的一直不深入.今天看了下json的官方资料,明了很多. json官方网址:http://www.json.org/json-zh.html JSON(J ...

  8. Newtonsoft.Json(Json.Net)学习笔记-高级使用(转)

    1.忽略某些属性 2.默认值的处理 3.空值的处理 4.支持非公共成员 5.日期处理 6.自定义序列化的字段名称 7.动态决定属性是否序列化 8.枚举值的自定义格式化问题 9.自定义类型转换 10.全 ...

  9. Newtonsoft.Json(Json.Net)学习笔记(转)

    概述 Newtonsoft.Json,一款.NET中开源的Json序列化和反序列化类库,通过Nuget获取.(查看原文) 下面是Json序列化和反序列化的简单封装: /// <summary&g ...

随机推荐

  1. [C++] 获取IE代理服务器的账号密码

    很多程序需要使用'浏览器设置'的代理服务器,IE设置的代理服务器有可能是需要账号密码的.怎样编程获取浏览器设置的代理服务器的账号密码呢? InternetQueryOption(NULL, INTER ...

  2. 如何查看 Python 全部内置变量和内置函数?

    https://jingyan.baidu.com/article/7082dc1c071649e40a89bdb8.html Python 解释器内置了一些常量和函数,叫做内置常量(Built-in ...

  3. 原生Js 实现等比缩放页面

    针对1920*1080 分配率缩放 window.addEventListener('load', adaptation); window.addEventListener('resize', ada ...

  4. 浅谈使用spring security中的BCryptPasswordEncoder方法对密码进行加密与密码匹配

    浅谈使用springsecurity中的BCryptPasswordEncoder方法对密码进行加密(encode)与密码匹配(matches) spring security中的BCryptPass ...

  5. VMware虚拟机安装Windows2003操作教程

    1.下载好以下三个文件: 2.选择VMware安装包,跟随指令安装好后,打开: 3.选择"创建新的虚拟机"后,选择"安装光盘映像文件(iso)",点击浏览载入. ...

  6. Linux 内核PCI去除一个设备

    一个 PCI 可用多个不同的方法被从系统中去除. 所有的 card-bus 设备在一个不同的物 理因素上是真正的 PCI 设备, 并且内核 PCI 核心不区分它们. 允许在机器运行时加减 PCI 设备 ...

  7. 北京信息科技大学第十一届程序设计竞赛E-- kotori和素因子(深搜)

    链接:https://ac.nowcoder.com/acm/contest/940/E 题目描述 kotori拿到了一些正整数.她决定从每个正整数取出一个素因子.但是,kotori有强迫症,她不允许 ...

  8. HDU 6662 Acesrc and Travel (换根dp)

    Problem Description Acesrc is a famous tourist at Nanjing University second to none. During this sum ...

  9. 改变this指向

    fn.call(obj,参数,参数): call(函数执行过程中this指向,后面的参数就是原函数的参数列表) : 函数下的一个内置方法,当我们申明一个函数的时候,这个函数下就会有一个默认的方法,ca ...

  10. 【Docker】删除镜像

    删除镜像:docker rmi [OPTIONS] IMAGE [IMAGE...] 1.删除所有未被 tag 标记和未被容器使用的镜像: docker image prune 2.删除所有未被容器使 ...