To add to Alex' answer:
String processing comes with a lot of overhead (e.g. support for UTF-8 operations). For smart contracts it's important that they are small in terms of size, this reduces the gas fees for users as well as the throughput a blockchain can achieve when multiple contracts are called in one block.
By using String's the entire code bloat for being able to handle them has to be included in the smart contract, thus making them way bigger than they need to be.
If you're in need for e.g. parsing JSON then that's something that should definitely be done on the side of the user interface/client/Dapp and only the result of the parsing should be submitted.
If you're really in need to store something human readable you could make it a
Vec<u8> instead of a String ‒ thus avoiding the inclusion of any String processing overhead.
If you're really really in need of String, then ink! exposes it via the crate
ink_prelude::String (see https://paritytech.github.io/ink/ink_prelude/string/index.html).