javascript - 未捕获的 SyntaxError : Unexpected end of JSON input. 无法正确地将 html 中的信息解析为 JSON

标签 javascript python json django

使用ajax查询产品后尝试打开包含产品详细信息的模式时出现错误

错误本身:

Uncaught SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at HTMLButtonElement.<anonymous> (scripts.js:54)
at HTMLDocument.dispatch (jquery-3.3.1.js:5183)
at HTMLDocument.elemData.handle (jquery-3.3.1.js:4991)

需要明确的是:我有一些过滤器,其结果在 python filter_items 函数中过滤,然后使用 JSONResponse 将其发送到前端 以字典的形式(Item 模型中的 as_dict() 函数)将它们添加到隐藏输入值中。 JS 函数获取隐藏的输入值并使用该输入中的数据呈现过滤结果。

借助过滤功能查询的项目模型:

class Item(models.Model):

ITEM_TYPES = (
    ('UM', 'Umbrella'),
    ('SK', 'Skirt'),
    ('TR', 'Trousers'),
    ('OT', 'Other')
)

BRANDS = (
    ('VS', 'Versace'),
    ('SP', 'Supreme'),
    ('SI', 'Stone Island'),
    ('FP', 'Fred Perry'),
)

title = models.CharField(max_length=256)
image = models.ImageField(upload_to='img/')
brand = models.CharField(max_length=256)
type = models.CharField(choices=ITEM_TYPES, max_length=2)
description = models.TextField(blank=True, null=True)
season = models.TextField(blank=True, null=True)
discount = models.FloatField(blank=True, null=True)
price = models.FloatField()

def __str__(self):
    return self.title + ' ' + self.type

def as_dict(self):
    data = {"title": self.title, "image": self.image.url, "brand": self.brand, "type": self.type,
            "discount": self.discount, "price": self.price, "rus_representation": self.rus_representation,
            "description": self.description, "season": self.season, "images": [self.image.url]}

    if self.images:
        for image in self.images.all():
            data['images'].append(image.image.url)

    # data['dumped'] = json.dumps(data)
    # print(data['dumped'])
    return data

def dumped_as_dict(self):
    return json.dumps(self.as_dict())

@property
def rus_representation(self):

    if self.type == 'UM':
        return 'Зонтик'
    elif self.type == 'SK':
        return 'Юбка'
    elif self.type == 'TR':
        return 'Штаны'
    elif self.type == 'OT':
        return 'Другое'

基于类的 View ,其中包含过滤功能:

class ProductsListView(ListView):
model = Item
types = Item.ITEM_TYPES
brands = Item.BRANDS

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['types'] = self.types
    context['brands'] = self.brands
    return context

@classmethod
def filter_items(cls, request, *args, **kwargs):
    if request.is_ajax():
        data = request.GET

        queryset = Item.objects.all()

        if not data['type'] == 'ALL':
            queryset = queryset.filter(type=data['type'])

        if not data['brand'] == 'ALL':
            queryset = queryset.filter(brand__contains=data['brand'])
        return JsonResponse({'result': [item.as_dict() for item in queryset]})

JavaScript过滤函数:

    $('.choice-link').click(function () {
    var choice = $(this).text();

    $(this).siblings().attr('id', '');

    $(this).attr('id', 'active');

    $(this).parent().parent().children('button').text(choice);

    var data = {
        'brand': $('.brand-dropdown').children('#active').attr('data-choice'),
        'type': $('.type-dropdown').children('#active').attr('data-choice')
    };

    $.ajax({
        url: '../ajax/filter/',
        data: data,
        success: function (data) {
            $('.item-block').remove();
            $.each(data.result, function (index, item) {
                if (!item.discount) {
                    var el = '<div class="item-block flex" style="flex-direction: column"><input type="hidden" value='+ JSON.stringify(item) +'><img class="img-fluid" style="box-shadow: 0 0 10px rgba(0,0,0,0.5);" src="' + item.image + '"><h6 class="item-title">' + item.rus_representation + ' "' + item.brand + '"<hr></h6><p class="flex" style="align-items: flex-start"><span class="price-tag">' + item.price + ' $</span></p><button type="button" class="item-btn btn-sm btn btn-outline-info" data-toggle="modal" data-target=".details-modal">Подробней <img style="height: 10px" "></button></div>';
                } else {
                    var el = '<div class="item-block flex" style="flex-direction: column"><input type="hidden" value='+ JSON.stringify(item) +'><img class="img-fluid" style="box-shadow: 0 0 10px rgba(0,0,0,0.5);" src="' + item.image + '"><h6 class="item-title">' + item.rus_representation + ' "' + item.brand + '"<hr></h6><p class="flex" style="align-items: flex-start"><span class="price-tag">' + item.price + ' $</span><span class="discount badge badge-danger">' + item.discount + ' $</span></p><button type="button" class="item-btn btn-sm btn btn-outline-info" data-toggle="modal" data-target=".details-modal">Подробней <img style="height: 10px" "></button></div>';
                }
                $('.items-list').children('hr').after(el)
            });

        }
    })
});

用相关数据填充模态的 Java 脚本函数:

$(document).on('click', '.item-btn', function () {
var data = JSON.parse($(this).siblings('input').val()); (line 54 where error message points)

$('.product-title').html(data.rus_representation + ' "<i>' + data.brand + '</i>"' + '<hr>');

if(data.description) {
    $('.product-description').text(data.description);
}else{
    $('.product-description').html('<h4>Описнаие пока не добавлено</h4>')
}

$('.carousel-inner').empty();
$.each(data.images, function (index, img) {
    if(index === 0){
        var el = '<div class="carousel-item active"><img class="d-block w-100" src="'+ img +'"></div>'
    } else {
        var el = '<div class="carousel-item"><img class="d-block w-100" src="'+ img +'"></div>'
    }

    $('.carousel-inner').append(el)
});

$('.product-brand').html('<i>' + data.brand + '</i>');
$('.product-type').text(data.rus_representation);
$('.product-season').text(data.season);

if (data.discount){
    $('.discount-in-modal').html('<span class="discount badge badge-danger" style="position: relative; top: -5px">'+ data.discount +' $</span>');
}

$('.product-price').text(data.price);

});

HTML:

            {% for item in object_list %}
            <div class="item-block flex" style="flex-direction: column">
                <input type="hidden" value="{{ item.dumped_as_dict }}">
                <img class="img-fluid" style="box-shadow: 0 0 10px rgba(0,0,0,0.5); max-height: 300px" src="{{ item.image.url }}">
                <h6 class="item-title">
                    {{item.rus_representation}} "{{item.brand}}"
                    <hr>
                </h6>
                <p class="flex" style="align-items: flex-start">
                    <span class="price-tag">{{ item.price }} $</span>
                    {% if item.discount %}
                        <span class="discount badge badge-danger">{{ item.discount }} $</span>
                    {% endif %}
                </p>
                <button type="button" class="item-btn btn-sm btn btn-outline-info" data-toggle="modal" data-target=".details-modal">Подробней <img style="height: 10px" src="{% static 'img/arrow.png' %}"></button>
            </div>
        {% endfor %}

IF do console.log(JSON.stringify(item));:

{"title":"tst","image":"/media/img/_58A1259_sm.jpg","brand":"GUCCI","type":"SK","discount":9000000,"price":9,"rus_representation":"Юбка","description":"LoL Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.","season":"","images":["/media/img/_58A1259_sm.jpg","/media/img/_58A7975_sm.jpg"]}

它应该是什么样子:

opening the modal on initial load

我有:

if use filtering and them trying to open details modal

从检查器添加 View : For some reasons string is not fully added to value attr

最佳答案

当您构建该 HTML 字符串时,您的代码会执行如下操作:

var el = '<div ... value=' + JSON.stringify(x) + ' ... >';

HTML 结果将是

var el = '<div ... value={ ... } ... >';

由于“value”的属性值在生成的 HTML 源中未加引号,因此对于 HTML 解析器而言,JSON 中的第一个空格字符是属性值的结尾。

您至少需要包含引号:

var el = '<div ... value=\'' + JSON.stringify(x) + '\' ... >';

我还强烈建议您使用 HTML 实体编码器对字符串中的任何 HTML 元字符进行编码,例如

function scrubHtml(s) {
  return s.replace(/[<>'"&]/g, function(meta) {
    return "&#" + meta.charCodeAt(0) + ";";
  });
}

关于javascript - 未捕获的 SyntaxError : Unexpected end of JSON input. 无法正确地将 html 中的信息解析为 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53970986/

相关文章:

javascript - 在 Tumblr 中重定向特定页面的问题

javascript - 是否有可能通过编写 javascript 代码或 JQuery 代码在新窗口中打开 anchor 标记

python - 函数的时间复杂度

python - 使用 Pandas 确定一个 CSV 文件中的值是否在另一个 CSV 文件中丢失

c# - 使用 JSON 和 JQuery 将数组发布到 C# Web Api 后端

ios - Swift 3 TableView Segue 到多个其他 TableView

asp.net - 如何在 JavaScript 中找到 ASP.NET TreeView 节点的父节点?

javascript - ChartJS : Draw vertical line at data point on chart on mouseover

python - VSCode ModuleNotFoundError : No module named X

json - jq substr() 相当于格式化一个值