skip to Main Content

I’m not comfortable with this heavy escaping in my curls

curl -X POST -H "Content-Type:application/json" -d "{"username":"john","password":"12345"}" http://localhost:8100/signup

I read this answer. Single quotes are not accepted

curl -X POST -H "Content-Type:application/json" -d '{"username":"john","password":"12345"}' http://localhost:8100/signup 
org.springframework.core.codec.DecodingException: 
JSON decoding error: Unexpected character (''' (code 39)): 
expected a valid value (JSON String, Number, Array, Object or token 'null', 'true' or 'false')

This doesn’t work as well (the exception is the same)

curl -X POST -H "Content-Type:application/json" -d "{'username':'john','password':'12345'}" http://localhost:8100/signup  

My curl version:

curl --version                                                                       
curl 8.4.0 (Windows) libcurl/8.4.0 Schannel WinIDN                                                  
Release-Date: 2023-10-11                                                                            
Protocols: dict file ftp ftps http https imap imaps pop3 pop3s smtp smtps telnet tftp               
Features: AsynchDNS HSTS HTTPS-proxy IDN IPv6 Kerberos Largefile NTLM SPNEGO SSL SSPI threadsafe Unicode UnixSockets 

Can I do without that aggressive escaping when executing my curls with JSON payload (without payload files)?

UPD

I debugged and discovered the exception is thrown from com.fasterxml.jackson.core.json.UTF8StreamJsonParser on a nextToken() invocation if its _inputBuffer (a byte array) starts with an apostrophe

I tried to write an MRE. It’s tricky. The class has a ton of parameters, some of them are tricky to instantiate. Here’s my best attempt. It does reproduce the error but since I pass nulls and mocks I can’t be sure I actually mimic the actual case. Basically, if the method reaches the end without recognition of the first character (it has lots of ifs and switch cases), it throws that exception

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.core.json.UTF8StreamJsonParser;
import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;

import java.io.InputStream;

import static org.assertj.core.api.Assertions.assertThatCode;
import static org.mockito.Mockito.mock;

public class GenericTest {
    @Test
    @SneakyThrows
    void test() {
        IOContext context = mock(IOContext.class);
        int features = 65537;
        InputStream inputStream = null;
        ObjectCodec codec = null;
        ByteQuadsCanonicalizer canonicalizer = null;
        String input = "'{}'";
        byte[] inputBuffer = input.getBytes();
        int start = 0;
        int end = input.length();
        byte bytesPreProcessed = 0;
        boolean bufferRecycleable = true;

        UTF8StreamJsonParser jsonParser = new UTF8StreamJsonParser(
                context, features, inputStream, codec,
                canonicalizer, inputBuffer, start, end,
                bytesPreProcessed, bufferRecycleable
                );

        assertThatCode(jsonParser::nextToken)
                // the exception is translated and rethrown by Spring
                .isInstanceOf(JsonParseException.class)
                .hasMessageContaining("Unexpected character (''' (code 39))");
    }
}

UPD2

I tried Power Shell instead of Command Prompt. I couldn’t make a request even with escaping, Shell threw all kinds of exceptions no matter what I tried

Attempt #1

curl -i -X POST -H "Content-Type:application/json" -d "{"username":"john","password":"12345"}" http://localhost:8100/signup 
    + CategoryInfo          : InvalidArgument: (:) [Invoke-WebRequest], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Attempt #2

curl -i -X POST -H Content-Type:application/json -d {"username":"john","password":"12345"} http://localhost:8100/signup
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken

Attempt #3

curl -i -X POST -H Content-Type:application/json -d {username:john,password:12345} http://localhost:8100/signup
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingArgument

Attempt #4

curl -i -X POST -H Content-Type:application/json -d '{"username":"john","password":"12345"}' http://localhost:8100/signup
    + CategoryInfo          : InvalidArgument: (:) [Invoke-WebRequest], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Attempt #5

curl -i -X POST -H 'Content-Type:application/json' -d '{"username":"john","password":"12345"}' http://localhost:8100/signup
    + CategoryInfo          : InvalidArgument: (:) [Invoke-WebRequest], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

2

Answers


  1. Use a different shell (not cmd.exe or PowerShell), which supports single quotes for quoting command arguments. For example, Bash supports it. Bash is available on Windows e.g. in WSL2 and MSYS2.

    This works in Bash:

    curl -X POST -H "Content-Type:application/json" -d '{"username":"john","password":"12345"}' http://localhost:8100/signup
    

    Alternatively, save the POST data to a file, and ask curl to read it from the file.

    Login or Signup to reply.
  2. Linux Bash

    -d '{"username":"john","password":"12345"}'
    

    Windows CMD

    -d "{"username":"john","password":"12345"}"
    

    Windows PowerShell

    -d '{"username":"john","password":"12345"}'
    

    I’m not comfortable with this heavy escaping in my curls

    By adding JSON as a string, there’s unfortunately no other way around it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search