jq를 사용하여 JSON 문자열 값에서 이스케이프된 슬래시를 유지합니다.

jq를 사용하여 JSON 문자열 값에서 이스케이프된 슬래시를 유지합니다.

JSON 사양에 따르면 슬래시는 사용할 수 없습니다.가지다백슬래시로 탈출하지만 그들은할 수 있는예.
호환성 이유로 문자열 값(키 내부는 아님) 내의 모든 슬래시가 이스케이프되는 JSON 파일이 있습니다.

{
  "proto://some/path": "\/\/some\/path"
}

그러나 jq다음 백슬래시는 자동으로 제거됩니다.

$ echo '{"proto://some/path":"\/\/some\/path"}' | jq -c .
{"proto://some/path":"//some/path"}

출력이 필요합니다.{"proto://some/path":"\/\/some\/path"}

jq문자열 값을 변경하지 않고 백슬래시를 유지하도록 어떻게 알 수 있나요 ?
또는 이러한 백슬래시를 다시 추가하는 방법이 있습니까?값에만 해당체험 후에는 jq?

답변1

당신이 할 수 있다면 나는 놀랄 것입니다. jq입력을 디코딩하고 작업을 수행하며 결과 개체를 json으로 인코딩합니다. 인코딩 및 출력 시 출력은 JSON 인코딩 문자열이며 s \앞의 s 정보는 /오랫동안 손실되었습니다. 만약 그것들이 /원래 쓰여졌 다면 같은 일이 일어날 것입니다 \u002f. 같은 이유로 , as , as 등 으로 jq다시 포맷된다는 것을 알 수 있습니다.1.011e2100INF1.7976931348623157e+308

그러나 JSON은 Perl 정규식 등을 사용하여 수동으로 안정적으로 처리할 수 있는 비교적 간단한 파일 형식입니다.

객체 key 를 제외한 모든 문자열의 \모든 문자열 앞에 s 를 다시 추가 하려면 다음을 수행하면 됩니다./

jq... |
  perl -0777 -pe '
    s{"(?:\\.|.)*?"(\s*:)?}{
      $1 ? $& : $& =~ s{/}{\\/}gr
    }ge'

"s와 s가 포함된 문자열이 있어도 제대로 작동합니다 \(예 : ).{"key": "//\"//\\"}

대안으로 슬래시를 이스케이프 처리하도록 지시할 수 있는 jqJSON::PP perl모듈을 사용할 수 있습니다(모든 문자열에 표시되지만).

$ json_pp -json_opt escape_slash < your-file
{"proto:\/\/some\/path":"\/\/some\/path"}

이미 익숙하다면 학습 곡선이 구문 학습만큼 가파르지 perl않을 것입니다 .jq

어떤 경우든 JSON 형식을 사용하면 /s를 이스케이프할 수 있지만 \/(또는 \u002f모든 문자와 유사하게) 필수는 아닙니다. 내가 온라인에서 읽은 바에 따르면 이것이 허용되므로 </HTML 태그를 작성하여 HTML 태그 내에 포함된 JSON 문자열을 삽입할 수 있습니다. 이것이 일부 JSON 인코더가 이를 인코딩하는 이유입니다. 이는 이식성을 높이기 때문입니다. 그러나 JSON이 HTML처럼 포함되도록 의도되지 않은 경우에는 아마도 중요하지 않을 것입니다. 그렇다면 객체 키를 포함하여 모든 곳에서 이 인코딩을 사용하고 싶을 것입니다.<script>"<\/whatever"\//

답변2

JSON에서 인코딩해야 하는 문자열을 모르는 일부 프로세스가 저장해야 한다고 생각하는 리터럴 문자열을 삽입했지만 인코딩하지 않았다고 가정합니다. 백슬래시는 이스케이프할 필요가 없는 이스케이프 문자이고 백슬래시 자체가 리터럴 백슬래시를 이스케이프하지 않기 때문에 jq문자열을 추출 및 디코딩하거나 다른 이유로 문서를 처리하는 데 사용될 때 "사라지는" 것처럼 보입니다.

요컨대,앞으로슬래시는 이스케이프 처리할 필요가 없지만(이스케이프 처리는 사실상 아무 작업도 하지 않음) 백슬래시를 문자 그대로 백슬래시로 유지하려면 백슬래시를 이스케이프 처리해야 합니다.

다음은 문서의 모든 문자열 값을 각각 다음과 같이 재귀적으로 변경합니다 /( \\/이것은 JSON 문자열에 쓰는 방법입니다). 표현식이 데이터를 처리할 때 파서가 백슬래시를 제거했다는 \/점을 기억하십시오 .jqjq

jq 'walk(if type == "string" then gsub("/"; "\\/") else . end)' file

주어진 예제 문서에 대해 다음이 생성됩니다.

{
  "proto://some/path": "\\/\\/some\\/path"
}

수정된 문서에서 인코딩된 문자열 값을 추출하고 디코딩하면 다음이 제공됩니다 \/\/some\/path.

$ jq 'walk(if type == "string" then gsub("/"; "\\/") else . end)' file | jq -r '."proto://some/path"'
\/\/some\/path

처음부터 생성하면 다음과 같은 JSON 문서가 생성됩니다.

$ jq -n --arg 'proto://some/path' '\/\/some\/path' '$ARGS.named'
{
  "proto://some/path": "\\/\\/some\\/path"
}

관련 정보