mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-02 17:08:32 +00:00
fix: handle prettifying json data with bruno variables (#6038)
This commit is contained in:
@@ -8,7 +8,7 @@ import { humanizeRequestBodyMode } from 'utils/collections';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
import { updateRequestBody } from 'providers/ReduxStore/slices/collections/index';
|
||||
import { toastError } from 'utils/common/error';
|
||||
import fastJsonFormat from 'fast-json-format';
|
||||
import { prettifyJsonString } from 'utils/common/index';
|
||||
import xmlFormat from 'xml-formatter';
|
||||
|
||||
const RequestBodyMode = ({ item, collection }) => {
|
||||
@@ -39,7 +39,7 @@ const RequestBodyMode = ({ item, collection }) => {
|
||||
const onPrettify = () => {
|
||||
if (body?.json && bodyMode === 'json') {
|
||||
try {
|
||||
const prettyBodyJson = fastJsonFormat(body.json);
|
||||
const prettyBodyJson = prettifyJsonString(body.json);
|
||||
dispatch(
|
||||
updateRequestBody({
|
||||
content: prettyBodyJson,
|
||||
|
||||
@@ -10,7 +10,7 @@ import React, { useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { autoDetectLang } from 'utils/codemirror/lang-detect';
|
||||
import { toastError } from 'utils/common/error';
|
||||
import fastJsonFormat from 'fast-json-format';
|
||||
import { prettifyJsonString } from 'utils/common/index';
|
||||
import xmlFormat from 'xml-formatter';
|
||||
import WSRequestBodyMode from '../BodyMode/index';
|
||||
|
||||
@@ -105,7 +105,7 @@ export const SingleWSMessage = ({
|
||||
const onPrettify = () => {
|
||||
if (codeType === 'json') {
|
||||
try {
|
||||
const prettyBodyJson = fastJsonFormat(content);
|
||||
const prettyBodyJson = prettifyJsonString(content);
|
||||
const currentMessages = [...(body.ws || [])];
|
||||
currentMessages[index] = {
|
||||
...currentMessages[index],
|
||||
|
||||
@@ -2,6 +2,7 @@ import { customAlphabet } from 'nanoid';
|
||||
import xmlFormat from 'xml-formatter';
|
||||
import { JSONPath } from 'jsonpath-plus';
|
||||
import fastJsonFormat from 'fast-json-format';
|
||||
import { patternHasher } from '@usebruno/common/utils';
|
||||
|
||||
// a customized version of nanoid without using _ and -
|
||||
export const uuid = () => {
|
||||
@@ -293,7 +294,7 @@ export const formatResponse = (data, dataBufferString, mode, filter, bufferThres
|
||||
}
|
||||
|
||||
try {
|
||||
return fastJsonFormat(rawData);
|
||||
return prettifyJsonString(rawData);
|
||||
} catch (error) {}
|
||||
|
||||
if (typeof data === 'string') {
|
||||
@@ -322,3 +323,17 @@ export const formatResponse = (data, dataBufferString, mode, filter, bufferThres
|
||||
|
||||
return safeStringifyJSON(data, !isVeryLargeResponse);
|
||||
};
|
||||
|
||||
export const prettifyJsonString = (jsonDataString) => {
|
||||
if (typeof jsonDataString !== 'string') return jsonDataString;
|
||||
try {
|
||||
const { hashed, restore } = patternHasher(jsonDataString);
|
||||
const formattedJsonDataStringHashed = fastJsonFormat(hashed);
|
||||
const formattedJsonDataString = restore(formattedJsonDataStringHashed);
|
||||
return formattedJsonDataString;
|
||||
} catch (error) {
|
||||
console.log('error formatting json data!');
|
||||
console.error(error);
|
||||
}
|
||||
return jsonDataString;
|
||||
};
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
humanizeDate,
|
||||
relativeDate,
|
||||
getContentType,
|
||||
formatSize
|
||||
formatSize,
|
||||
prettifyJsonString
|
||||
} from './index';
|
||||
|
||||
describe('common utils', () => {
|
||||
@@ -191,4 +192,97 @@ describe('common utils', () => {
|
||||
expect(formatSize(NaN)).toBe('0B');
|
||||
});
|
||||
});
|
||||
|
||||
describe('prettifyJsonString', () => {
|
||||
test('should return non-string inputs unchanged', () => {
|
||||
expect(prettifyJsonString(null)).toBe(null);
|
||||
expect(prettifyJsonString(undefined)).toBe(undefined);
|
||||
expect(prettifyJsonString(123)).toBe(123);
|
||||
expect(prettifyJsonString([])).toEqual([]);
|
||||
expect(prettifyJsonString({})).toEqual({});
|
||||
expect(prettifyJsonString(true)).toBe(true);
|
||||
});
|
||||
|
||||
test('should format valid JSON without Bruno variables', () => {
|
||||
const input = '{"name":"John","age":30}';
|
||||
const expected = `{\n "name": "John",\n "age": 30\n}`;
|
||||
console.log(prettifyJsonString(input));
|
||||
expect(prettifyJsonString(input)).toBe(expected);
|
||||
});
|
||||
|
||||
test('should format valid JSON with Bruno variables', () => {
|
||||
const input = '{"name": {{userName}}}';
|
||||
const expected = `{\n "name": {{userName}}\n}`;
|
||||
console.log(prettifyJsonString(input));
|
||||
expect(prettifyJsonString(input)).toBe(expected);
|
||||
});
|
||||
|
||||
test('should format complex json string', () => {
|
||||
const input = `{"id": 123456789123456789123456789,"name": "Test 'JSON' Data with "quotes" — Pretty Print ","active": true,"price": 199.9999999,"decimals": 1.00,"nullValue": null,"unicodeText": "こんにちは世界 ","escapedCharacters": "Line1\nLine2\tTabbed\"Quoted\" and 'single quoted' with 'code' style","nestedObject": { "level1": { "level2": { "emptyArray": [], "specialChars": "@#$%^&*()_+-=[]{}|;':,./<>?~", "booleanValues": [ true, false, true ], "numbers": [ 0, -1, 1.23e10, 3.1415926535 ] } }},"mixedArray": [ "string with 'apostrophe'", 42, false, null, { "innerObj": { "keyWithQuotes": "value containing \`backticks\` and 'single quotes'", "nestedArray": [ { "a": "O'Reilly" }{ "b": "'inline code'" }, [ "deep", "array", { "c": "contains 'quotes'" } ] ] } }],"nonStringVariable": {{nonStringVar}},"withBrunoVariable": "{{string}} '{{with}}' "{{variety}}" of '{{variables}}'","dateExample": "2025-11-07T12:34:56Z","regexExample": "^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$","urls": { "website": "https://example.com?param='value'&flag='true'", "escapedURL": "https:\/\/escaped-url.com\/path\?q='search'\&debug='on'"},"multiLineString": "This is a long text\nthat spans multiple\nlines with \`backticks\` 'quotes' and 'code' snippets "}`;
|
||||
const expectedOutput = `{
|
||||
"id": 123456789123456789123456789,
|
||||
"name": "Test 'JSON' Data with "quotes" — Pretty Print ",
|
||||
"active": true,
|
||||
"price": 199.9999999,
|
||||
"decimals": 1.00,
|
||||
"nullValue": null,
|
||||
"unicodeText": "こんにちは世界 ",
|
||||
"escapedCharacters": "Line1\nLine2\tTabbed\"Quoted\" and 'single quoted' with 'code' style",
|
||||
"nestedObject": {
|
||||
"level1": {
|
||||
"level2": {
|
||||
"emptyArray": [],
|
||||
"specialChars": "@#$%^&*()_+-=[]{}|;':,./<>?~",
|
||||
"booleanValues": [
|
||||
true,
|
||||
false,
|
||||
true
|
||||
],
|
||||
"numbers": [
|
||||
0,
|
||||
-1,
|
||||
1.23e10,
|
||||
3.1415926535
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"mixedArray": [
|
||||
"string with 'apostrophe'",
|
||||
42,
|
||||
false,
|
||||
null,
|
||||
{
|
||||
"innerObj": {
|
||||
"keyWithQuotes": "value containing \`backticks\` and 'single quotes'",
|
||||
"nestedArray": [
|
||||
{
|
||||
"a": "O'Reilly"
|
||||
}{
|
||||
"b": "'inline code'"
|
||||
},
|
||||
[
|
||||
"deep",
|
||||
"array",
|
||||
{
|
||||
"c": "contains 'quotes'"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"nonStringVariable": {{nonStringVar}},
|
||||
"withBrunoVariable": "{{string}} '{{with}}' "{{variety}}" of '{{variables}}'",
|
||||
"dateExample": "2025-11-07T12:34:56Z",
|
||||
"regexExample": "^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$",
|
||||
"urls": {
|
||||
"website": "https://example.com?param='value'&flag='true'",
|
||||
"escapedURL": "https:\/\/escaped-url.com\/path\?q='search'\&debug='on'"
|
||||
},
|
||||
"multiLineString": "This is a long text\nthat spans multiple\nlines with \`backticks\` 'quotes' and 'code' snippets "
|
||||
}`;
|
||||
expect(prettifyJsonString(input)).toBe(expectedOutput);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { forOwn } from 'lodash';
|
||||
import curlToJson from './curl-to-json';
|
||||
import fastJsonFormat from 'fast-json-format';
|
||||
import { prettifyJsonString } from 'utils/common/index';
|
||||
|
||||
export const getRequestFromCurlCommand = (curlCommand, requestType = 'http-request') => {
|
||||
const parseFormData = (parsedBody) => {
|
||||
@@ -67,7 +67,7 @@ export const getRequestFromCurlCommand = (curlCommand, requestType = 'http-reque
|
||||
body.file = parsedBody;
|
||||
}else if (contentType.includes('application/json')) {
|
||||
body.mode = 'json';
|
||||
body.json = fastJsonFormat(parsedBody);
|
||||
body.json = prettifyJsonString(parsedBody);
|
||||
} else if (contentType.includes('xml')) {
|
||||
body.mode = 'xml';
|
||||
body.xml = parsedBody;
|
||||
|
||||
@@ -7,3 +7,7 @@ export {
|
||||
export {
|
||||
buildFormUrlEncodedPayload
|
||||
} from './form-data';
|
||||
|
||||
export {
|
||||
patternHasher
|
||||
} from './template-hasher';
|
||||
|
||||
Reference in New Issue
Block a user