```json
{
  "sym_variables": [
    ("x0", "lilies"),
    ("x1", "petunias"),
    ("x2", "zucchini vines")
  ],
  "objective_function": "6*x0 + 4*x1 + 5*x2",
  "constraints": [
    "5*x0 + 2*x1 + 3*x2 <= 122",
    "6*x0 + 1*x1 + 6*x2 <= 53",
    "3*x0 + 7*x1 + 4*x2 <= 106",
    "7*x1 + 4*x2 >= 31",
    "3*x0 + 7*x1 >= 25",
    "5*x0 + 3*x2 <= 97",
    "5*x0 + 2*x1 <= 89",
    "2*x1 + 3*x2 <= 84",
    "5*x0 + 2*x1 + 3*x2 <= 85",
    "6*x0 + 6*x2 <= 47",
    "1*x1 + 6*x2 <= 25",
    "6*x0 + 1*x1 + 6*x2 <= 25",
    "3*x0 + 7*x1 <= 48",
    "3*x0 + 4*x2 <= 101",
    "3*x0 + 7*x1 + 4*x2 <= 66",
    "x0 == int(x0)",
    "x1 == int(x1)",
    "x2 == int(x2)"
  ]
}
```

```python
import gurobipy as gp

try:
    # Create a new model
    m = gp.Model("garden_optimization")

    # Create variables
    lilies = m.addVar(vtype=gp.GRB.INTEGER, name="lilies")
    petunias = m.addVar(vtype=gp.GRB.INTEGER, name="petunias")
    zucchini_vines = m.addVar(vtype=gp.GRB.INTEGER, name="zucchini_vines")

    # Set objective function
    m.setObjective(6*lilies + 4*petunias + 5*zucchini_vines, gp.GRB.MAXIMIZE)

    # Add constraints
    m.addConstr(5*lilies + 2*petunias + 3*zucchini_vines <= 122, "water_need")
    m.addConstr(6*lilies + 1*petunias + 6*zucchini_vines <= 53, "beauty_rating")
    m.addConstr(3*lilies + 7*petunias + 4*zucchini_vines <= 106, "planting_space")
    m.addConstr(7*petunias + 4*zucchini_vines >= 31, "petunias_zucchini_space")
    m.addConstr(3*lilies + 7*petunias >= 25, "lilies_petunias_space")
    m.addConstr(5*lilies + 3*zucchini_vines <= 97, "lilies_zucchini_water")
    m.addConstr(5*lilies + 2*petunias <= 89, "lilies_petunias_water")
    m.addConstr(2*petunias + 3*zucchini_vines <= 84, "petunias_zucchini_water")
    m.addConstr(5*lilies + 2*petunias + 3*zucchini_vines <= 85, "total_water")
    m.addConstr(6*lilies + 6*zucchini_vines <= 47, "lilies_zucchini_beauty")
    m.addConstr(1*petunias + 6*zucchini_vines <= 25, "petunias_zucchini_beauty")
    m.addConstr(6*lilies + 1*petunias + 6*zucchini_vines <= 25, "total_beauty")
    m.addConstr(3*lilies + 7*petunias <= 48, "lilies_petunias_space_limit")
    m.addConstr(3*lilies + 4*zucchini_vines <= 101, "lilies_zucchini_space_limit")
    m.addConstr(3*lilies + 7*petunias + 4*zucchini_vines <= 66, "total_space_limit")


    # Optimize model
    m.optimize()

    if m.status == gp.GRB.OPTIMAL:
        print('Obj: %g' % m.objVal)
        print('lilies:', lilies.x)
        print('petunias:', petunias.x)
        print('zucchini_vines:', zucchini_vines.x)
    elif m.status == gp.GRB.INFEASIBLE:
        print('The model is infeasible.')
    else:
        print('Optimization ended with status %d' % m.status)


except gp.GurobiError as e:
    print('Error code ' + str(e.errno) + ': ' + str(e))

except AttributeError:
    print('Encountered an attribute error')
```