### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current Behavior

When creating a SNS Subscription and setting the attribute `FilterPolicy` to `""` causes an 500 internal server error

### Expected Behavior

SNS Subscription is created without a `FilterPolicy`. This is the behaviour in AWS and is the way to unset the `FilterPolicy`

### How are you starting LocalStack?

With a `docker run` command

### Steps To Reproduce

#### How are you starting localstack (e.g., `bin/localstack` command, arguments, or `docker-compose.yml`)

`docker run --rm -p 4566:4566 -p 4510-4559:4510-4559 --env DEBUG=1 --env LS_LOG=trace --name localstack localstack/localstack:latest`

#### Client commands (e.g., AWS SDK code snippet, or sequence of "awslocal" commands)
    
```bash
export AWS_ENDPOINT_URL=http://localhost:4566 AWS_ACCESS_KEY_ID=fake AWS_SECRET_ACCESS_KEY=fake
aws sqs create-queue --queue-name queue.fifo --attributes FifoQueue=true
aws sns create-topic --name topic.fifo --attributes FifoTopic=true
aws sns subscribe --topic-arn arn:aws:sns:eu-central-1:000000000000:topic.fifo --protocol "sqs" --notification-endpoint arn:aws:sqs:eu-central-1:000000000000:queue.fifo --attributes FilterPolicy=""
```

### Environment

```markdown
- OS: MacOS Sonoma
- LocalStack version: 3.0.3.dev
```


### Anything else?

Setting `FilterPolicy` to `""` is the way to remove it from AWS

Logs from the container:

```python
2024-01-06T23:27:41.587  INFO --- [   asgi_gw_0] localstack.request.aws     : AWS sns.Subscribe => 500 (InternalError); 000000000000/eu-central-1; SubscribeInput({'TopicArn': 'arn:aws:sns:eu-central-1:000000000000:topic.fifo', 'Protocol': 'sqs', 'Endpoint': 'arn:aws:sqs:eu-central-1:000000000000:queue.fifo', 'Attributes': {'FilterPolicy': ''}}, headers={'Host': 'localhost:4566', 'Accept-Encoding': 'identity', 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'User-Agent': 'aws-cli/2.15.7 Python/3.11.7 Darwin/23.2.0 source/arm64 prompt/off command/sns.subscribe', 'X-Amz-Date': '20240106T232741Z', 'Authorization': 'AWS4-HMAC-SHA256 Credential=fake/20240106/eu-central-1/sns/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=c16cc33fc710b0882c33e396c5d9e07852a672a0961d37489052d04b5dde7ed6', 'Content-Length': '246', 'x-moto-account-id': '000000000000'}); InternalError(exception while calling sns.Subscribe: Traceback (most recent call last):
  File "/opt/code/localstack/localstack/aws/chain.py", line 99, in handle
    handler(self, self.context, response)
  File "/opt/code/localstack/localstack/aws/handlers/service.py", line 112, in __call__
    handler(chain, context, response)
  File "/opt/code/localstack/localstack/aws/handlers/service.py", line 82, in __call__
    skeleton_response = self.skeleton.invoke(context)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/localstack/aws/skeleton.py", line 154, in invoke
    return self.dispatch_request(serializer, context, instance)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/localstack/aws/skeleton.py", line 168, in dispatch_request
    result = handler(context, instance) or {}
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/localstack/aws/forwarder.py", line 135, in _call
    return handler(context, req)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/localstack/aws/skeleton.py", line 118, in __call__
    return self.fn(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/localstack/services/sns/provider.py", line 601, in subscribe
    moto_response = call_moto(context)
                    ^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/localstack/services/moto.py", line 48, in call_moto
    return dispatch_to_backend(context, dispatch_to_moto, include_response_metadata)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/localstack/aws/forwarder.py", line 187, in dispatch_to_backend
    http_response = http_request_dispatcher(context)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/localstack/services/moto.py", line 119, in dispatch_to_moto
    response = dispatch(request, raw_url, request.headers)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/moto/core/responses.py", line 245, in dispatch
    return cls()._dispatch(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/moto/core/responses.py", line 446, in _dispatch
    return self.call_action()
           ^^^^^^^^^^^^^^^^^^
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/moto/core/responses.py", line 540, in call_action
    response = method()
               ^^^^^^^^
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/moto/sns/responses.py", line 238, in subscribe
    self.backend.set_subscription_attributes(
  File "/opt/code/localstack/.venv/lib/python3.11/site-packages/moto/sns/models.py", line 756, in set_subscription_attributes
    filter_policy = json.loads(value)
                    ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
, headers={'Content-Type': 'text/xml', 'Content-Length': '3686'})
```
subscribe_resp = subscribe_queue_to_topic(
            {
                "RawMessageDelivery": "true",
            }
        )
        snapshot.match("subscribe-exact-same-raw", subscribe_resp)
        subscribe_resp = subscribe_queue_to_topic(
            {
                "RawMessageDelivery": "true",
                "FilterPolicyScope": "MessageAttributes",  
            }
        )
        snapshot.match("subscribe-idempotent", subscribe_resp)
        
        subscribe_resp = subscribe_queue_to_topic()
        snapshot.match("subscribe-idempotent-no-attributes", subscribe_resp)
        subscribe_resp = subscribe_queue_to_topic({})
        snapshot.match("subscribe-idempotent-empty-attributes", subscribe_resp)
        subscribe_resp = subscribe_queue_to_topic({"FilterPolicyScope": "MessageAttributes"})
        snapshot.match("subscribe-missing-attributes", subscribe_resp)
        with pytest.raises(ClientError) as e:
            subscribe_queue_to_topic(
                {
                    "RawMessageDelivery": "false",
                    "FilterPolicyScope": "MessageBody",
                }
            )
        snapshot.match("subscribe-diff-attributes", e.value.response)
    @markers.aws.validated
    def test_unsubscribe_idempotency(