To solve the given optimization problem, we first need to convert the natural language description into a symbolic representation. This involves defining variables, an objective function, and constraints based on the problem statement.

Let's define the variables as follows:
- $x_1$: Number of posters placed at the northside mall
- $x_2$: Number of posters placed at the southside mall
- $x_3$: Number of posters placed at the central mall

The objective function aims to maximize viewership. Given that each poster at the northside mall attracts 20,000 viewers, at the southside mall attracts 50,000 viewers, and at the central mall attracts 40,000 viewers, the objective function can be represented as:
\[ \text{Maximize} \quad 20000x_1 + 50000x_2 + 40000x_3 \]

The constraints are based on the given limitations:
1. The southside mall limits the number of posters to 5: $x_2 \leq 5$
2. At most a third of the posters should be placed at the central mall: $x_3 \leq \frac{1}{3}(x_1 + x_2 + x_3)$
3. At least 20% of the posters should be placed at the northside mall: $x_1 \geq 0.2(x_1 + x_2 + x_3)$
4. The weekly budget is $30,000: $500x_1 + 1000x_2 + 800x_3 \leq 30000$
5. Non-negativity constraints: $x_1, x_2, x_3 \geq 0$

Symbolic representation in JSON format:
```json
{
    'sym_variables': [('x1', 'Number of posters at the northside mall'), 
                      ('x2', 'Number of posters at the southside mall'), 
                      ('x3', 'Number of posters at the central mall')],
    'objective_function': '20000*x1 + 50000*x2 + 40000*x3',
    'constraints': ['x2 <= 5', 
                    'x3 <= (1/3)*(x1 + x2 + x3)', 
                    'x1 >= 0.2*(x1 + x2 + x3)', 
                    '500*x1 + 1000*x2 + 800*x3 <= 30000',
                    'x1 >= 0', 'x2 >= 0', 'x3 >= 0']
}
```

Now, let's implement this problem using Gurobi in Python:

```python
from gurobipy import *

# Create a model
m = Model("Poster_Placement")

# Define variables
x1 = m.addVar(vtype=GRB.INTEGER, name="northside_mall")
x2 = m.addVar(vtype=GRB.INTEGER, name="southside_mall")
x3 = m.addVar(vtype=GRB.INTEGER, name="central_mall")

# Objective function: Maximize viewership
m.setObjective(20000*x1 + 50000*x2 + 40000*x3, GRB.MAXIMIZE)

# Constraints
m.addConstr(x2 <= 5, "southside_limit")
m.addConstr(x3 <= (1/3)*(x1 + x2 + x3), "central_mall_limit")
m.addConstr(x1 >= 0.2*(x1 + x2 + x3), "northside_minimum")
m.addConstr(500*x1 + 1000*x2 + 800*x3 <= 30000, "budget_constraint")

# Optimize the model
m.optimize()

# Print results
for v in m.getVars():
    print(f"{v.varName}: {v.x}")

print(f"Objective Value: {m.objVal}")
```