简体   繁体   English

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

[英]Angular 2 pipe that transforms JSON object to pretty-printed JSON

Trying to write an Angular 2 pipe that will take a JSON object string and return it pretty-printed/formatted to display to the user.尝试编写一个 Angular 2 管道,该管道将采用 JSON 对象字符串并将其返回漂亮打印/格式化以显示给用户。

For example, it would take this:例如,它会这样:

{ "id": 1, "number": "K3483483344", "state": "CA", "active": true } { "id": 1, "number": "K3483483344", "state": "CA", "active": true }

And return something that looks like this when displayed in HTML:并在 HTML 中显示时返回如下所示的内容:

在此处输入图像描述

So in my view I could have something like:所以在我看来,我可以有类似的东西:

<td> {{ record.jsonData | prettyprint }} </td>

I would like to add an even simpler way to do this, using the built-in json pipe:我想添加一个更简单的方法来做到这一点,使用内置的json管道:

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

This way, the formatting is preserved.这样,格式就被保留了。

I would create a custom pipe for this:我会为此创建一个自定义管道:

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

and use it this way:并以这种方式使用它:

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

See this stackblitz: https://stackblitz.com/edit/angular-prettyprint请参阅此堆栈闪电战: https ://stackblitz.com/edit/angular-prettyprint

I had required this scenario and many times require it.我曾经需要这种情况,而且很多次都需要它。 I saw this question is still trending in 2021. So I created a detailed post explaining not how to just prettify it but add colors to it and built a small tool to play around with.我看到这个问题在 2021 年仍然很流行。所以我创建了一篇详细的帖子,解释了如何不仅美化它,还为它添加颜色,并构建了一个小工具来玩。

2021 solution: I built my own custom version of pipe (inspried by this answer ) which not only prettifies but also adds colors to JSON like vscode . 2021 解决方案:我构建了自己的自定义管道版本(受此答案启发),它不仅可以美化,还可以像 vscode 一样为 JSON 添加颜色 I don't use a built-in JSON pipe because it doesn't serve my full purpose.我不使用内置的 JSON 管道,因为它不能满足我的全部目的。

This also gives you the freedom to add number lines and padding if you wish to.如果您愿意,这也使您可以自由添加数字行和填充。 Try to play around even with the nested jsons!尝试使用嵌套的 jsons!

Sample output like below示例输出如下

演示

global stylesheet should contain colors as per your theme for eg styles.scss全局样式表应包含根据您的主题的颜色,例如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;
  }
}

Source code of the pipe管道源代码

@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;
  }
}

now pass these params inside HTML like this.现在像这样在 HTML 中传递这些参数。 If you don't pass it by default value of showNumberline is false and padding is 4如果你不通过默认值showNumberline是 false 并且padding是 4

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

Hope this helps🙂希望这有帮助🙂

As this is the first result on google, let me add a quick sum up:由于这是谷歌上的第一个结果,让我快速总结一下:

  • if you only need to print JSON without proper formatting, the build-in json pipe suggested by Shane Hsu works perfectly: <pre>{{data | json}}</pre>如果您只需要在没有正确格式的情况下打印 JSON,Shane Hsu 建议的内置json管道可以完美运行: <pre>{{data | json}}</pre> <pre>{{data | json}}</pre>

  • however, if you want to have a different output, you will need to create your own pipe as Thierry Templier suggested:但是,如果您想获得不同的输出,则需要按照 Thierry Templier 的建议创建自己的管道:

    1. ng g generate pipe prettyjson
    2. in prettyjson.pipe.ts:在 prettyjson.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. Finally, and because we return HTML content, the pipe must be used inside an innerHTML function:最后,因为我们返回 HTML 内容,管道必须在innerHTML函数中使用:
<div [innerHTML]="data | prettyjson"></div>

since my variable is two way binded with ngModel, I could not do it on html.由于我的变量是与 ngModel 绑定的两种方式,因此我无法在 html 上执行此操作。 I used on component side JSON.stringify(displayValue, null, 2) and it did the job.我在组件端使用JSON.stringify(displayValue, null, 2)并完成了这项工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM