将 JSON 对象转换为打印漂亮的 JSON 的角度2管道

尝试编写一个 Angular 2管道,该管道将接受一个 JSON 对象字符串,并将其完美打印/格式化以显示给用户。

例如,它会采取这样的措施:

{ “ id”: 1, “编号”: “ K3483483344” “州”“ CA” “活跃”: 正确 }

并返回在 HTML 中显示时如下所示的内容:

enter image description here

所以在我看来,我可以有这样的东西:

<td> {{ record.jsonData | prettyprint }} </td>
146401 次浏览

我将为此创建一个自定义管道:

@Pipe({
name: 'prettyprint'
})
export class PrettyPrintPipe implements PipeTransform {
transform(val) {
return JSON.stringify(val, null, 2)
.replace(' ', '&nbsp;')
.replace('\n', '<br/>');
}
}

用这种方式:

@Component({
selector: 'my-app',
template: `
<div [innerHTML]="obj | prettyprint"></div>
`,
pipes: [ PrettyPrintPipe ]
})
export class AppComponent {
obj = {
test: 'testttt',
name: 'nameeee'
}
}

看看这个堆栈闪电战: https://stackblitz.com/edit/angular-prettyprint

我想添加一个更简单的方法来做到这一点,使用内置的 json管道:

<pre>\{\{data | json}}</pre>

这样可以保留格式。

由于这是谷歌的第一个搜索结果,让我简单总结一下:

  • 如果您只需要打印 JSON 而不需要正确的格式,那么 Shane Hsu 建议的内置 json管道可以很好地工作: <pre>\{\{data | json}}</pre>

  • 然而,如果你想要一个不同的输出,你需要像 Thierry Templier 建议的那样创建你自己的管道:

    1. ng g generate pipe prettyjson
    2. 在 pretyjson.pipe.ts:
import { Pipe, PipeTransform } from '@angular/core';


@Pipe({
name: 'prettyjson'
})
export class PrettyjsonPipe implements PipeTransform {


transform(value: any, ...args: any[]): any {
return JSON.stringify(value, null, 2)
.replace(/ /g, '&nbsp;') // note the usage of `/ /g` instead of `' '` in order to replace all occurences
.replace(/\n/g, '<br/>'); // same here
}


}
  1. 最后,因为我们返回 HTML 内容,管道必须在 innerHTML函数中使用:
<div [innerHTML]="data | prettyjson"></div>

因为我的变量是与 ngModel 双向绑定的,所以不能在 html 上执行。我使用的组件端 JSON.stringify(displayValue, null, 2)和它的工作。

我需要这个场景,而且很多次都需要它。我看到这个问题在2021年仍然很流行。因此,我创建了一个详细的职位,解释不只是如何美化它,但添加到它的颜色,并建立了一个小工具,以发挥围绕。

2021年 + 解决方案: 我构建了自己的 自定义版本的管道(灵感来自这个回答 ) ,它不仅可以美化 JSON,而且可以像 vscode 一样给 JSON 添加颜色。我不使用内置的 JSON 管道,因为它不能完全满足我的需要。

这也给你自由添加数字行和填充,如果你愿意。

样本输出如下

Demo

全局样式表应该按照主题包含颜色,例如 styles.scss

pre {
font-weight: 400;


.number-line {
color: #adadaf;
}
.string {
color: #95c602;
}
.number {
color: #f2b619;
}
.boolean {
color: #0097f1;
}
.null {
color: #727990;
}
.key {
color: #fff;
}
}

管道源代码

@Pipe({
name: 'prettyjson',
pure:true
})
export class PrettyJsonPipe implements PipeTransform {
transform(value: any, args: any[]): any {
try {
/**
* check and try to parse value if it's not an object
* if it fails to parse which means it is an invalid JSON
*/
return this.applyColors(
typeof value === 'object' ? value : JSON.parse(value),
args[0],
args[1]
);
} catch (e) {
return this.applyColors({ error: 'Invalid JSON' }, args[0], args[1]);
}
}


applyColors(obj: any, showNumebrLine: boolean = false, padding: number = 4) {
// line number start from 1
let line = 1;


if (typeof obj != 'string') {
obj = JSON.stringify(obj, undefined, 3);
}


/**
* Converts special charaters like &, <, > to equivalent HTML code of it
*/
obj = obj.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
/* taken from https://stackoverflow.com/a/7220510 */


/**
* wraps every datatype, key for e.g
* numbers from json object to something like
* <span class="number" > 234 </span>
* this is why needed custom themeClass which we created in _global.css
* @return final bunch of span tags after all conversion
*/
obj = obj.replace(
/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
(match: any) => {
// class to be applied inside pre tag
let themeClass = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
themeClass = 'key';
} else {
themeClass = 'string';
}
} else if (/true|false/.test(match)) {
themeClass = 'boolean';
} else if (/null/.test(match)) {
themeClass = 'null';
}
return '<span class="' + themeClass + '">' + match + '</span>';
}
);


/**
* Regex for the start of the line, insert a number-line themeClass tag before each line
*/
return showNumebrLine
? obj.replace(
/^/gm,
() =>
`<span class="number-line pl-3 select-none" >${String(line++).padEnd(padding)}</span>`
)
: obj;
}
}

现在像这样在 HTML 中传递这些参数。如果你不传递它的默认值为 showNumberline为 false,而 padding为4

<pre [innerHTML]="dummyJsonObject | prettyjson: [true, 3]"></pre>

希望这个能帮上忙。