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

Der*_*rek 77 javascript json pipe filter angular

尝试编写一个Angular 2管道,该管道将获取一个JSON对象字符串并将其返回相当打印/格式化以显示给用户.

例如,它需要:

{"id":1,"number":"K3483483344","州":"CA","有效":true}

并在HTML中显示时返回看起来像这样的内容:

在此输入图像描述

所以在我看来,我可以有类似的东西:

<td> {{ record.jsonData | prettyprint }} </td>
Run Code Online (Sandbox Code Playgroud)

Sha*_*Hsu 245

我想使用内置json管道添加一种更简单的方法:

<pre>{{data | json}}</pre>
Run Code Online (Sandbox Code Playgroud)

这样,格式化得以保留.

  • 凉爽的。请注意,格式需要“&lt;pre&gt;”,并且不适用于“&lt;p&gt;”、“&lt;span&gt;”等。 (6认同)
  • 很明显,我给了你一个观点,因为我为寻找它而感到羞耻:p (4认同)
  • 如果你的`data`是`object`就可以工作 (3认同)
  • 另外,如果您的 json 是嵌套的且未格式化,请更新您的 css 以使用带有空格的 pre 元素: pre-wrap (2认同)

min*_*eek 32

我曾经需要这个场景,并且多次需要它。我看到这个问题在 2021 年仍然很流行。所以我创建了一篇详细的帖子,解释如何不仅美化它,还为其添加颜色,并构建了一个小工具来玩。

2021+ 解决方案: 我构建了自己的自定义版本的管道(受到此答案的启发),它不仅可以美化,还可以像 vscode 一样向 JSON 添加颜色。我不使用内置 JSON 管道,因为它不能满足我的全部目的。

如果您愿意,这还使您可以自由添加数轴和填充。

示例输出如下

演示

全局样式表应包含根据您的主题的颜色,例如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;
  }
}
Run Code Online (Sandbox Code Playgroud)

管道源代码

@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 /sf/answers/505435731/ */

    /**
     * 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在像这样在 HTML 中传递这些参数。如果不传递默认值为showNumberlinefalse 且padding为 4

@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;
  }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。


Thi*_*ier 19

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

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

并以这种方式使用它:

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

请参阅stackblitz:https://stackblitz.com/edit/angular-prettyprint


Dla*_*eme 7

由于这是谷歌上的第一个结果,让我快速总结一下:

  • 如果您只需要在没有正确格式的情况下打印 JSON json,Shane Hsu 建议的内置管道可以完美运行:<pre>{{data | json}}</pre>

  • 但是,如果您想要不同的输出,则需要按照 Thierry Templier 的建议创建自己的管道:

    1. ng g generate pipe prettyjson
    2. 在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
  }

}
Run Code Online (Sandbox Code Playgroud)
  1. 最后,因为我们返回 HTML 内容,所以必须在innerHTML函数内部使用管道:
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
  }

}
Run Code Online (Sandbox Code Playgroud)


Fen*_*ang 5

由于我的变量以两种方式与 ngModel 绑定,因此我无法在 html 上执行此操作。我在组件方面使用它JSON.stringify(displayValue, null, 2) 并且完成了工作。