Suggest: let json.dumps keeps non-ASCII characters when sending json request

## Summary
When I send a json request, the json.dumps **does not keeps non-ASCII characters**. 

## Reproduction Steps

```
cat <<MM | python3 - &
from flask import Flask,request
app = Flask('')

@app.route('/', methods=['POST', 'GET'])
def test():
    return(request.data)

app.run()
MM

cat <<MM | python3 -
import time
import requests as r
time.sleep(1)
print(r.post('http://localhost:5000/', json={'bar':'程序员'}).text)
MM

```
## Expected Result
I expect result keeps *non-ASCII* request:
`{"bar": "程序员"}`
## Actual Result
`{"bar": "\u7a0b\u5e8f\u5458"}`

## Suggest
Modify the models `vim modles.py +458` to keep the non-ASCII characters. 
For example:

`body = complexjson.dumps(json, ensure_ascii=False)`
```
 >>> json.dumps('程序员', ensure_ascii=False)
'"程序员"'
>>> json.dumps('程序员')
'"\\u7a0b\\u5e8f\\u5458"'

```


## System Information

    $ python -m requests.help

```
{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": ""
  },
  "implementation": {
    "name": "CPython",
    "version": "3.6.1"
  },
  "platform": {
    "release": "15.6.0",
    "system": "Darwin"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.18.1"
  },
  "system_ssl": {
    "version": "100020cf"
  },
  "urllib3": {
    "version": "1.21.1"
  },
  "using_pyopenssl": false
}
```

Does

```py

cat <<MM | python3 -
import json
import time
import requests as r
time.sleep(1)
print(r.post('http://localhost:5000/', data=json.dumps({'bar':'程序员'}), headers={'Content-Type': 'application/json'}).text)
MM
```

Do the right thing?

Also, looking at our source code: https://github.com/requests/requests/blob/b66908e7b647689793e299edc111bf9910e93ad3/requests/models.py#L454

I see:

```py
        if not data and json is not None:
            # urllib3 requires a bytes-like body. Python 2's json.dumps
            # provides this natively, but Python 3 gives a Unicode string.
            content_type = 'application/json'
            body = complexjson.dumps(json)
            if not isinstance(body, bytes):
                body = body.encode('utf-8')
```

Which is unclear if that's what you're complaining about. Furthermore, you haven't given us any of the information we kindly requested. So we'll need that before we can move forward.

Please provide us with the output of

```
python -m requests.help
```

If that is unavailable on your version of Requests please provide some basic information about your system (Python version, operating system, etc).

@sigmavirus24 I've updated this issue with more info. 
I hope the json request could keep non-ASCII.
For the purposes of:

1. Decrease the size of data
2. Convenient for debugging and reading.

@ahui132 please answer my [question](https://github.com/requests/requests/issues/4580#issuecomment-379777337). Your issue now includes the baseline information but is still unclear. Are you suggesting adding `ensure_ascii=True` to every call?

> Are you suggesting adding ensure_ascii=True to every call?

@sigmavirus24 No, I want to set `ensure_ascii=False` by default. 

Hi @ahui132, I think you may be suggesting we set `ensure_ascii` to `False`, not `True`. If you look at the method signature in both [Python 2](https://docs.python.org/2/library/json.html#basic-usage) and [Python 3](https://docs.python.org/3/library/json.html#basic-usage), you'll see it's already set to True by default. 

It looks like we are doing something a bit off here. When you use dumps with the json module, the ensure_ascii flag escapes all unicode strings. When we call `encode('utf-8')`, we are escaping the escape strings which means we send `\\u7a0b\\u5e8f]\u5458` instead of `\u7a0b\u5e8f\u5458`. I'm pretty sure that's not what we want, since the receiving json decoder with think the string is literally `\u7a0b\u5e8f\u5458` not `程序员` without building in a custom decoder.

So setting `ensure_ascii` to False means we won't double escape and do actually send what we're expecting. I'm not sure how this change would affect existing users, or how we've had this functionality around so long without it being called out. I've run out of investigation time today but if anyone wants to build some tests around this, that would be a great start.

@nateprewitt I'm not sure I follow. Which of the following do you feel is correct:

```py
>>> import json
>>> json.dumps({'bar':'程序员'})
'{"bar": "\\u7a0b\\u5e8f\\u5458"}'
>>> json.dumps({'bar':'程序员'}).encode('utf-8')
b'{"bar": "\\u7a0b\\u5e8f\\u5458"}'
>>> json.dumps({'bar':'程序员'}, ensure_ascii=False)
'{"bar": "程序员"}'
>>> json.dumps({'bar':'程序员'}, ensure_ascii=False).encode('utf-8')
b'{"bar": "\xe7\xa8\x8b\xe5\xba\x8f\xe5\x91\x98"}'
```

```py
>>> print(requests.post('https://httpbin.org/post', headers={'Content-Type': 'application/json'}, data=json.dumps({'bar':'程序员'}).encode('utf-8')).text)
{
  "args": {}, 
  "data": "{\"bar\": \"\\u7a0b\\u5e8f\\u5458\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "29", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.18.4"
  }, 
  "json": {
    "bar": "\u7a0b\u5e8f\u5458"
  }, 
  "origin": "127.127.127.127", 
  "url": "https://httpbin.org/post"
}

>>> print(requests.post('https://httpbin.org/post', headers={'Content-Type': 'application/json'}, data=json.dumps({'bar':'程序员'}, ensure_ascii=False).encode('utf-8')).text)
{
  "args": {}, 
  "data": "{\"bar\": \"\u7a0b\u5e8f\u5458\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "20", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.18.4"
  }, 
  "json": {
    "bar": "\u7a0b\u5e8f\u5458"
  }, 
  "origin": "127.127.127.127", 
  "url": "https://httpbin.org/post"
}
```

As far as I can tell they both have the same result.

😅This is what I get for writing quick and dirty tests. I was using the data field which does change based on ensure_ascii, but the `json` modules handles this the same (`\`==`\\`, `\\\`==`\\\\`, etc). I was comparing strings rather than the loaded JSON objects which caused the inconsistency.

@ahui132, this is working as expected. Your server is receiving [json-escaped strings](https://tools.ietf.org/html/rfc8259#section-7) which are valid according to the spec. You'll also note that the spec requires all JSON data transferred between systems to be represented this way. If you want the json contents to return to their "expected" form, you'll find calling `r.content.decode('unicode_escape')` should do the trick.

@nateprewitt @sigmavirus24 
Let me make a summarization
## json string's format: Non-ASCII vs ASCII
The json-escaped raw string `"{\"bar\": \"\\u5458\"}"` is different from `"{\"bar\": \"\u5458\"}"`.
1. The first one is pure ASCII format, and the second is non-ASCII format
2. Both of them are valid json escaped format.

```

>>> json.dumps('\u5458', ensure_ascii=True) # ASCII
'"\\u5458"'
>>> len(json.dumps('\u5458', ensure_ascii=True).encode('utf8'))
8
>>> json.dumps('\u5458', ensure_ascii=False) # non-ASCII
'"员"'
>>> '"\u5458"' # non-ASCII
'"员"'
>>> len(json.dumps('\u5458', ensure_ascii=False).encode('utf8'))
5
```
## How to send json with non-ASCII format
I we want to send json with non-ASCII via requests, we have to use `post` method with `Content-Type: appliaction/json` explicitly(It's too complex):
1. `print(requests.post('https://httpbin.org/post', headers={'Content-Type': 'application/json'}, data=json.dumps({'bar':'员'}, ensure_ascii=False).encode('utf-8')).text)`

I think there are some pythonic ways as blow:
1. Add an `ensure_ascii` option: `print(requests.post('https://httpbin.org/post', json={'bar':'员'}, ensure_ascii=False)).text)`
2. Set `ensure_ascii=False` by default in `vim modles.py +458`

This project is not adding new keywords that are related to serialization. If you need this specific handling, then the first way that is *explicit* is the only right way to do it.

It's not too complex, as `json` is API sugar for the 98% use-case. The last 2% simply will not get API sugar around that. That's the design credo of this project.